arrayhelper::merge()是唯一推荐的嵌套合并方式,因其能正确处理多层结构、保留数字键顺序并支持字符串键深度覆盖;其他函数如+、array_merge()、array_merge_recursive()均存在覆盖或重排缺陷。

配置数组覆盖规则不是框架内置机制,而是你写的那几行 require 和 ArrayHelper::merge() 决定的。 没有“默认覆盖逻辑”,只有你手动控制的合并顺序和函数行为。
为什么 ArrayHelper::merge() 是唯一推荐的嵌套合并方式
它能正确处理多层结构(比如 'components' => ['db' => [...], 'cache' => [...]]),同时保留数字键顺序、字符串键深度覆盖。其他函数会出问题:
-
+运算符:只做顶层补缺,'components'整个子数组会被右侧直接替换,不是合并字段 -
array_merge():遇到同名数字键(如日志targets列表)会重编号,打乱执行顺序 -
array_merge_recursive():对同名数字键也重排,且无法区分“覆盖值”和“追加值”
main.php 和 web.php 的加载顺序不能反
典型写法是:
$config = yii\helpers\ArrayHelper::merge(
require __DIR__ . '/main.php',
require __DIR__ . '/web.php'
);
这意味着:
-
main.php在前 → 提供基础配置(id、basePath、通用components) -
web.php在后 → 只覆盖需要差异化的内容(如request、response、urlManager) - 如果反过来,
web.php里没定义的'bootstrap' => []会被main.php的空数组清掉,导致模块不启动
容易静默失效的三个坑
这些错误不会报错,但配置就丢了:
-
main.php里写了'components' => []:ArrayHelper::merge()会把它当空数组,web.php中定义的所有组件都被忽略 - 局部配置文件(如
params-local.php)没在main.php或web.php里require:Yii 完全不知道它的存在 - 模块内试图用
\Yii::configure($this, require 'config/main.php')加载参数:模块不是应用实例,$this->params不会自动映射,应直接定义public $params = [];并在init()中赋值
真正要盯住的只有两件事:你 require 的顺序,和你选的合并函数是否匹配配置结构。嵌套深就用 ArrayHelper::merge(),扁平就用 + 或 array_replace(),别混着来。











