array_merge_recursive 对数字键不重编号,而是按位置附加值并保留原键;仅对字符串键递归合并,数字键下将同键值统一转为数组后堆叠。

array_merge_recursive 对数字键不重编号,但会附加而非覆盖
不会重新编号。array_merge_recursive 在处理数字键时,行为与 array_merge 不同:它不会重置或连续重排数字索引,而是将后一个数组中相同位置(即相同整数键)的值**追加到原键对应值之后**,前提是原键对应的值也是数组;否则会自动转为数组再合并。
关键点在于:它只对**字符串键递归合并**,对数字键则按“位置附加”逻辑处理,且保留原始数字键名——只要不是冲突覆盖,就维持原样。
- 若两个数组都有键 0,且值都是字符串,array_merge_recursive 会把它们包进一个新数组:
[0 => ['a', 'x']] - 若键 0 的值一个是字符串、一个是数组,PHP 会尝试统一类型,通常将非数组转为数组再合并
- 键名如 5、100 这类整数索引会被原样保留,不会变成 0、1、2…
- 它不关心数字键是否“连续”,也不强制从 0 开始——这和 array_merge 的重编号机制有本质区别
和 array_merge 的核心差异
array_merge 遇到任意数字键就触发全局重编号;array_merge_recursive 完全不碰数字键的编号逻辑,只做内容层面的“堆叠”。
- array_merge([0=>'a', 2=>'c'], [1=>'b', 3=>'d']) → [0=>'a', 1=>'c', 2=>'b', 3=>'d'](全部重排)
- array_merge_recursive([0=>'a', 2=>'c'], [1=>'b', 3=>'d']) → [0=>'a', 1=>'b', 2=>'c', 3=>'d'](保持原键,顺序拼接)
- 真正体现递归的是字符串键:
['user'=>['name'=>'A'], 'user'=>['age'=>25]]合并后变成['user'=>['name'=>'A', 'age'=>25]]
注意边界情况
虽然数字键不重编号,但若多个数组在同一个数字键上提供不同类型的值(比如一个给字符串,一个给数组),结果可能不符合直觉。
-
array_merge_recursive([0=>'hello'], [0=>['world']])得到[0=>['hello', 'world']] -
array_merge_recursive([0=>['x']], [0=>'y'])同样得到[0=>[['x'], 'y']]('y' 被当做一个新元素追加) - 这不是错误,是设计使然:它把所有同键值统一视为“可合并单元”,数字键下也照此执行
什么时候该用 array_merge_recursive
适合需要保留原始结构、又希望多维数据层层叠加的场景,比如配置合并、表单多组提交、树形数据聚合。
- 要保留
[100=>'config_a', 200=>'config_b']这样的自定义索引?选它 - 想让
['db'=>['host'=>'a'], 'db'=>['port'=>3306]]自动合成['db'=>['host'=>'a','port'=>3306]]?选它 - 只是简单拼接一维列表且依赖顺序下标?array_merge 或 + 更直接
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











