Skip to main content
即使你为包添加了新的配置项,这些新项也不会自动写入用户之前发布的配置文件中。要在不破坏已发布配置的前提下补充默认值,你需要同时设计数组的合并策略和配置缓存。 本页将阅读 Laravel 13 的 ServiceProvider,整理如何将配置作为包的公开 API 进行维护。本页以Laravel 包开发为前提,并使用 laravel/framework 的 v13.34.0 来确认实现。

发布与合并是不同的处理

publishes() 注册复制的源路径和目标路径。在 vendor:publish 复制文件之前,用户的 config 目录不会发生变化。而 mergeConfigFrom() 则是在启动时更新配置仓库,并不会修改文件本身。
用户只在需要时才发布配置文件。即使不发布,在没有缓存的常规启动中,也会通过 register() 中的合并使用默认值。
如果在更新步骤中使用 --force 重新发布配置文件,会覆盖用户编辑过的内容。如果只是添加新的配置项,请优先采用补充默认值并说明变更内容的方式。

mergeConfigFrom() 只合并顶层

ServiceProvider::mergeConfigFrom() 会先传入包的配置,再传入应用的现有配置,然后执行 array_merge()。对于相同的字符串键,应用侧的值优先。 以下示例仅使用数组重现了框架的合并处理。
顶层的 enabled 会被补充,但 transport 整个数组会被替换,transport.retries 不会保留。关键在于:如果用户已经发布了旧的 transport 数组,即使你在同一个数组中添加新键,这些键也不会被补充。

使用 replaceConfigRecursivelyFrom() 补充嵌套配置

Laravel 13 的 ServiceProvider 中还有一个 protected 方法 replaceConfigRecursivelyFrom()。它以相同的顺序执行 array_replace_recursive()。 如果你希望配置 API 能够单独覆盖嵌套的字符串键,可以按如下方式修改提供者的 register()。对于同一个配置键,无需与前面的 mergeConfigFrom() 同时使用。
使用前面的 $defaults 和 $overrides,结果如下。
replaceConfigRecursivelyFrom() 是本页所确认的 Laravel 13 源代码中存在的方法。请将其与官方包开发文档介绍的 mergeConfigFrom() 区分开来,并在确认对应框架版本的实现后再使用。

数字键列表不会被整体替换

递归替换并不是”将数组全部替换为用户的值”的处理。对于数字键,它同样替换相同键的值,并保留用户未指定的键。
即使用户只指定了 ['slack'],database 仍会保留。另外,即使传入 ['channels' => []],默认列表也不会变为空。对于通知渠道或中间件等整体指定列表才有意义的配置,请特别注意。 如果你的包包含此类配置,请从配置结构入手考虑,例如将列表和可部分覆盖的关联数组拆分到不同的顶层键中,并使用浅层合并。对于已经发布的包,更改合并方式会导致同一个配置文件的行为发生变化,因此请不要将其仅仅视为实现层面的替换。

配置缓存中保存的是合并后的值

当应用实现了 CachesConfiguration 且 configurationIsCached() 为 true 时,这两个方法都会跳过合并处理。在常规的 Laravel 应用中,存在配置缓存的启动就属于这种情况。 ConfigCacheCommand 会删除旧的配置缓存,启动一个新的应用并获取整个配置仓库。在这次启动中,提供者的配置会被合并,结果保存到缓存文件中。之后的启动中,LoadConfiguration 会读取这些值。 因此,即使更新包后默认值或合并方式发生了变化,继续使用旧缓存的应用也不会反映这些变化。在使用配置缓存的部署中,请使用更新后的代码重新构建缓存。
如果你想在开发过程中恢复为从文件重新读取的状态,请使用 php artisan config:clear。不要自行决定缓存的生成位置,请交由 Laravel 的命令进行管理。
请不要在配置文件中定义 Closure,因为 config:cache 无法正确序列化它们。如果需要传递回调,请在配置中放置类名等内容,并在提供者中注册实际的服务。

发布配置变更前的检查

在包的测试中,不仅要处理未发布的配置,还要将旧版本遗留下来的配置作为输入。
  • 即使未发布配置,也能获取所需的默认值。
  • 对于旧的已发布配置,用户的值优先,且新项按设计被补充。
  • 对于嵌套数组、数字键列表和空数组,覆盖约定保持不变。
  • 在使用该包的应用中 config:cache 能够成功执行,并且在使用缓存的另一次启动中得到相同的配置。
请在发布说明中记录新键的默认值以及所需的缓存重建。对于键的删除、重命名或合并方式的变更,请将与用户已发布配置的兼容性一并纳入考量。

相关页面

包的测试

注册服务提供者,验证配置和服务的行为。

版本兼容性管理

将公开 API 的变更与发布策略和持续维护联系起来。

参考的一手资料

最后修改于 2026年10月1日