PHP中数组+运算符是左优先合并,右边同名键值被忽略;需覆盖应使用array_merge()或array_replace()。

PHP 中用 + 合并数组时右边键值被忽略
PHP 的 + 运算符对数组做的是「左优先合并」,不是覆盖式合并。右边数组中所有与左边**已有键名相同**的元素,都会被直接丢弃,连类型、顺序、引用关系都不参与比较——它根本不会尝试“更新”,只保留左边的原始值。
常见错误现象:$a = ['id' => 1, 'name' => 'A']; $b = ['name' => 'B', 'age' => 25]; var_dump($a + $b); 输出仍是 ['id' => 1, 'name' => 'A', 'age' => 25],'name' => 'B' 完全没出现。
-
+只按键名(key)匹配,不看键值(value),也不区分数字索引和字符串索引 - 数字键会被当作字符串处理(如
0和'0'视为同一键),容易引发隐式覆盖 - 如果右边有左边没有的键,才会追加;但只要键存在,右边就彻底失效
想覆盖合并该用 array_merge() 而不是 +
array_merge() 才是 PHP 中真正「以右为准」的覆盖式合并函数。它会逐个遍历参数数组,后出现的同名键会覆盖先出现的。
示例:$a = ['id' => 1, 'name' => 'A']; $b = ['name' => 'B', 'age' => 25]; var_dump(array_merge($a, $b)); 输出 ['id' => 1, 'name' => 'B', 'age' => 25],name 正确被替换。
立即学习“PHP免费学习笔记(深入)”;
- 数字索引会被重排(
[0] => 'x', [1] => 'y'合并后变成[0] => 'x', [1] => 'y', [2] => 'z') - 字符串键保留原名,后到的覆盖前到的
- 若需保留数字索引不重排,改用
array_replace()(PHP 5.3+)
array_replace() 更接近你直觉里的“右边覆盖左边”
array_replace() 不重排数字键,行为更贴近多数人对“合并并覆盖”的预期:同键名时右边生效,不同键名时补全,且不改变原有数字索引顺序。
对比:$a = [0 => 'a', 1 => 'b']; $b = [1 => 'B', 2 => 'c']; var_dump(array_replace($a, $b)); → [0 => 'a', 1 => 'B', 2 => 'c'];而 array_merge($a, $b) 会输出 [0 => 'a', 1 => 'B', 2 => 'c'] 表面一样,但若 $a = ['x' => 'a', 0 => 'b'],array_merge 会把 0 当新索引重排,array_replace 则严格按键操作。
-
array_replace()支持多维递归替换(需手动调用或配合array_replace_recursive()) - 它不修改原数组,返回新数组,和
+、array_merge()一致 - 注意:PHP 5.3 以下版本不可用,别在老环境硬套
为什么有人误以为 + 是“连接”?
因为对索引数组用 + 看起来像拼接:[1,2] + [3,4] 得到 [1,2](不是 [1,2,3,4]!),这是因数字键 0 和 1 已存在,右边的 0、1 被忽略。这种“看似拼上去了”的错觉,往往来自测试时用了带字符串键的数组,掩盖了问题。
- 永远不要用
+处理需要覆盖逻辑的场景 - 调试时用
var_dump(array_keys($arr))确认键名类型,尤其注意0vs'0' - CI/CD 或线上环境遇到合并结果异常,第一反应应查是否误用了
+而非array_merge
最常被忽略的一点:PHP 数组合并行为完全由键决定,而非“顺序”或“写法”。+ 的语义就是“左侧定义域优先”,它不承诺任何覆盖能力——把它当覆盖工具,等于拿扳手拧螺丝,能转两下,但迟早崩牙。



















