array_merge()合并索引数组会重排键为连续数字,+运算符保留左操作数键不覆盖,深度合并需用array_merge_recursive(),且所有参数必须为数组否则报错。

用 array_merge() 合并索引数组,但键会重排
如果你有两个纯数字键的数组,比如 $a = [1, 2] 和 $b = [3, 4],直接用 array_merge($a, $b) 得到的是 [1, 2, 3, 4] —— 键被自动重置为 0、1、2、3。这不是“覆盖”,而是设计如此。
常见错误是误以为它像 JS 的 concat 那样保留原键,结果后续用 foreach 或下标访问时出错。
- 只适用于你想合并后统一按顺序索引的场景
- 如果原数组有非连续数字键(如
[0 => 'a', 5 => 'b']),array_merge仍会重排成[0 => 'a', 1 => 'b'] - 遇到字符串键时,后者值会覆盖前者(见下一条)
用 + 运算符合并关联数组,键冲突时不覆盖
+ 是数组联合运算符,它按左操作数优先原则合并:左边有的键,右边同名键直接忽略,不覆盖。
例如:$a = ['x' => 1, 'y' => 2]; $b = ['y' => 99, 'z' => 3]; $a + $b 结果是 ['x' => 1, 'y' => 2, 'z' => 3]。注意 'y' 没被替换成 99。
立即学习“PHP免费学习笔记(深入)”;
- 仅对字符串键有效;数字键会被当作字符串处理,可能引发意外行为(如
[0 => 'a'] + [0 => 'b']仍得[0 => 'a']) - 不递归,嵌套数组会被整个替换,不是深度合并
- 性能略优于
array_merge(尤其大数组),因为不重排键、不校验类型
需要深度合并?别硬写,用 array_merge_recursive()
当数组里还有数组,你希望子数组也逐层合并而不是简单覆盖,就得用 array_merge_recursive()。
比如:$a = ['user' => ['name' => 'A']]; $b = ['user' => ['age' => 25]];,array_merge($a, $b) 会把 'user' 整个替换成第二个值,而 array_merge_recursive($a, $b) 得到 ['user' => ['name' => 'A', 'age' => 25]]。
- 遇到同名数字键时,值不会覆盖,而是变成新数组(如
[0 => 'x']和[0 => 'y']合并后是[0 => 'x', 1 => 'y']) - 不支持自定义合并逻辑(比如遇到同名字段想取最大值),这种得自己写递归函数
- PHP 8.1+ 开始支持
array_merge_recursive处理对象属性,但默认不推荐混用
合并前必须检查是否为数组,否则 array_merge() 报 Warning
array_merge() 所有参数都必须是数组,传入 null、string 或未定义变量,会触发 Warning: array_merge(): Expected parameter X to be an array。
常见于从配置或 API 返回中取值后直接合并,比如 array_merge($config['db'], $config['cache']),其中某个键不存在或为 null 就崩了。
- 稳妥做法:用
(array)$var强转,比如array_merge((array)$a, (array)$b) - 更明确的写法是加
is_array()判断,尤其在严格模式或生产环境 -
+运算符对非数组会直接报Fatal error,比array_merge更严厉,不能靠静默转换



















