本文分享下利用 Laravel 的 Bootstrapping 达到网站后台设置 laravel 配置。
需求场景
首先,ThinkSNS+ 作为一个用户可以使用的「社交系统」和开源网站程序一样拥有后台,有一些配置,Laravel 是要求写在 /config/*.php 的配置文件中的,例如 app.name、app.debug 等信息的配置,以及 Jobs 的驱动配置,广播系统的配置等,我们都搬到了网站后台,用户安装后可以不用修改配置文件的情况下镜像配置。
如何覆盖配置
我们首先打开 Illuminate\Foundation\Application::bootstrapWith 方法,代码如下:
重点代码在 $this['events']->fire('bootstrapping: '.$bootstrapper, [$this]); 和 $this['events']->fire('bootstrapped: '.$bootstrapper, [$this]); 上,很明显是加载并运行 bootstrapper 的前置和后置事件。
所以,我们看还有一个方法叫做 beforeBootstrapping 和 afterBootstrapping 然后怎么做呢?我们看
没错,这里是固定了顺序的,我错误的加载顺序,会造成laravel的失败,所以,我们选择在之前继承 Illuminate\Foundation\Application 的应用基础上增加一个事件,代码如下:
哪里添加的事件
因为 ThinkSNS+ 是继承了 Illuminate\Foundation\Application 实现了新的 Application 类,所以我们直接在构造方法里面增加了代码。
这样,当 Laravel 启动,但是还没有加载 bootstrapper 的时候,已经把 加载配置的后置事件注入进去了。当加载配置执行完成后就会执行我注入的后置事件。
后置事件的实现
我们在创建了 \Zhiyi\Plus\Bootstrap\LoadConfiguration 这样一个类,注册为后置事件,路径为: /app/Bootstrap/LoadConfiguration.php ,然后实现代码如下:
很简单,因为 app('config') 是一个 Illuminate\Contracts\Config\Repository 接口的实例,所以直接调用 set 方法进行配置覆盖。
而 Zhiyi\Plus\Support\Configuration 类是封装的自定义配置加载类,加载的配置文件存放在一个 YAML 文件中,这个类实现了 自定义配置文件的加载和保存。这样,我们从后台调用 API 然后 constroller 调用这个类的 save 方法进行持久化。
Zhiyi\Plus\Support\Configuration::getConfigurationBase
为什么要特殊说一下这个方法?因为这个方法的特殊性,也是 depth merge 实现的重要函数,在 Repository 中支持 app.name = value 这样的形式进行深曾键值赋值,利用这一个特性,这个函数将 多维数组转换为一维。
效果:
然后调用 app('config')->set($arr) 就对 Laravel 的 config 进行了 depth merge。
最后,持久化保存的 YAML 内容如下:
所以,基于 depth merge 在 .plus.yml 配置中,只需要保存部分配置,即可不想配置结构的完整性的情况下对 Laravel 镜像配置合并。
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。
在Laravel项目中,为了实现在网站后台动态设置配置项(如app.name
, app.debug
等),而不直接修改/config/*.php
文件,可以利用Laravel的Bootstrapping机制来覆盖和管理配置。以下是详细的步骤说明:
Illuminate\Foundation\Application::bootstrapWith
方法触发的前后置事件(bootstrapped
与bootstrapping
)。Illuminate\Foundation\Application
)构造函数中,注册一个后置事件监听器,确保在所有默认的Bootstrap过程完成后执行。Application
类构造函数内添加代码注册事件监听器,确保在配置加载完毕后执行自定义逻辑。public function __construct($basePath = null)
{
parent::__construct($basePath);
// 注册后置事件监听器以处理配置加载
$this->afterBootstrapping('config', function ($app) {
// 这里调用自定义的配置加载逻辑
$this['events']->dispatch(new LoadConfigurationEvent());
});
}
LoadConfiguration
类,该类应实现处理逻辑,用于从数据库或外部存储(如YAML文件)加载配置并覆盖到Laravel的配置系统中。namespace App\Bootstrap;
use Illuminate\Contracts\Foundation\Application;
use Illuminate\Support\Facades\Config;
class LoadConfiguration
{
public function handle(Application $app)
{
// 从数据库或其他数据源获取配置信息
$dynamicConfigs = $this->fetchDynamicConfigurations();
// 合并并设置配置
Config::set($dynamicConfigs);
}
protected function fetchDynamicConfigurations()
{
// 实现从数据库或特定服务获取动态配置的逻辑
}
}
depth merge
)技术确保新配置能正确地与现有配置合并,避免覆盖非目标配置项。Zhiyi\Plus\Support\Configuration
),负责读取(如从.plus.yml
)和写入配置到持久化存储。通过上述步骤,您可以在Laravel应用启动过程中动态地从后台管理界面设置的配置项覆盖默认配置,而无需手动编辑配置文件。这不仅提升了系统的灵活性,也便于运维管理和多环境配置的统一控制。