array_merge() 会重排所有数字键,从0开始连续编号;+运算符保留原始数字键但重复键被忽略;array_replace() 不重排数字键且同键覆盖。

array_merge() 会重排所有数字键,从 0 开始连续编号
这是最常被忽略的行为:只要任意一个输入数组含有数字键(哪怕只是 [10, 20] 这种隐式索引),array_merge() 就会把**所有数字键全部丢弃并重置**。字符串键不受影响,但数字键顺序和原始结构完全丢失。
常见错误现象:
- 原数组
$a = [0 => 'first', 'name' => 'Alice']和$b = [1 => 'second']合并后变成[0 => 'first', 1 => 'second', 'name' => 'Alice']—— 原来的1键没了,'name'位置也变了 - 想拼接两个索引数组却意外破坏了语义顺序(比如图片序号、步骤编号)
适用场景仅限于:你明确需要“扁平追加 + 重编号”,例如日志条目收集、批量插入前的归一化。
+ 运算符保留原始数字键,但重复键会被跳过
+ 不是加法,是「左侧优先联合」:它不会重排任何键,数字键照原样保留;但若左右两边都有相同数字键(如都含 0),右侧值直接被忽略,不是覆盖,是丢弃。
立即学习“PHP免费学习笔记(深入)”;
使用条件:
- 你必须确保左侧数组已包含所有需要保留的数字键
- 右侧只补充新键(如
1、2等尚未出现的索引) - 不能用于动态数量的数组合并(
$a + $b + $c等价于($a + $b) + $c,仍只保最左)
示例:$a = [0 => 'x']; $b = [0 => 'y', 1 => 'z']; $a + $b 结果是 [0 => 'x', 1 => 'z'] —— 0 来自 $a,1 来自 $b。
array_replace() 不重排数字键,且支持覆盖逻辑
如果你既要保留数字键结构,又希望同名键(包括数字键)能被右侧值覆盖,array_replace() 是更安全的选择。它对数字键和字符串键一视同仁:同键即替换,不重排、不丢弃、不追加。
注意点:
-
array_replace([0 => 'a', 'id' => 1], [0 => 'b', 'id' => 2])→[0 => 'b', 'id' => 2] - 它只做顶层替换,不递归;嵌套数组会被整个替换(如
'config' => [...]整体换掉) - 若需递归覆盖(比如只改嵌套里的某个字段),得用
array_replace_recursive()
数字键冲突时别依赖 array_merge_recursive()
array_merge_recursive() 对数字键的处理和 array_merge() 一样:**仍会重排**。它只在字符串键重复时才递归合并成数组,数字键重复时仍是“后追加+重编号”。所以它解决不了数字键结构保持问题。
容易踩的坑:
- 误以为 “recursive” 就等于 “尊重原始键”,结果数字键还是被重置了
- 混合使用字符串键和数字键时,
array_merge_recursive()行为更难预测(比如[0 => 'a']和['opt' => ['x' => 1]]合并,0还是变0,但语义已断裂)
真正要保数字键结构 + 支持覆盖,就别绕弯——array_replace() 是最直白、行为最可控的选项。



















