根本原因是键名冲突与合并策略误选:array_merge()对字符串键右侧覆盖左侧、数字键重索引;+运算符左优先,同键值静默忽略右侧;扩展运算符行为类似array_merge()但不支持null。

PHP合并数组时丢数据,根本原因就两条:键名冲突 + 合并策略没选对。不是函数坏了,是你没看清它怎么处理重复键。
array_merge() 用右侧覆盖左侧字符串键
这是最常踩的坑。只要两个数组里有同名字符串键,array_merge() 就直接用后一个值覆盖前一个,不警告、不报错、不提示。
- 比如
array_merge(['name' => 'Alice'], ['name' => 'Bob'])→['name' => 'Bob'],Alice 消失了 - 配置合并场景下,如果默认配置在前、用户配置在后,那没问题;但顺序反过来就丢配置
- 数字键不受影响:
array_merge([1,2], [3,4])→[1,2,3,4],因为数字键会被重索引,不触发覆盖
+ 运算符保留左侧、忽略右侧同键
+ 看似“加法”,实际是“左优先联合”——遇到相同键(无论字符串还是数字),一律跳过右侧值。
-
['a'=>1] + ['a'=>2]→['a'=>1],2 被静默丢弃 -
[0=>'x', 1=>'y'] + [0=>'z', 1=>'w']→[0=>'x', 1=>'y'],整个右侧被无视 - 适合补全默认值:
$config = $defaults + $user_input,确保用户只覆盖想改的项
扩展运算符 [...] 也按顺序覆盖字符串键
PHP 7.4+ 的 [...$a, ...$b] 行为更接近 array_merge(),但语法更紧凑。同样:字符串键后写入覆盖前写入,数字键重新索引。
立即学习“PHP免费学习笔记(深入)”;
-
['x'=>1, 'y'=>2] + ['y'=>3, 'z'=>4]和[...['x'=>1, 'y'=>2], ...['y'=>3, 'z'=>4]]结果一致:['x'=>1, 'y'=>3, 'z'=>4] - 区别在于:扩展运算符不能传 null 或非数组,
array_merge()会把 null 当空数组处理,而[...null]直接报Fatal error - 嵌套数组不会递归合并,只是扁平展开一层
真正容易被忽略的是:你根本没意识到自己在做键覆盖操作。尤其当数组来自不同来源(数据库查出、API返回、配置文件解析),键名看似不同,实则 PHP 自动做了类型转换(比如 "1" 和 1 当成同一键)。这时候丢数据,连错误日志都找不到痕迹。



















