array_merge对同名字符串键执行覆盖而非合并,如['tag'=>'php']与['tag'=>'mysql']合并后为['tag'=>'mysql'];数字键则追加并重排索引;需叠加值时应使用array_merge_recursive。

array_merge 会覆盖同名字符串键,不是“合并”而是“替换”
很多人以为 array_merge 能把同名键的值“合起来”,比如 ['tag' => 'php'] 和 ['tag' => 'mysql'] 合成 ['tag' => ['php', 'mysql']] —— 实际不会。array_merge 对字符串键只做覆盖:['tag' => 'mysql'] 直接替代前面的值。
常见错误现象:
- 调用
array_merge($a, $b)后发现某个键“不见了”,其实是被后一个数组悄悄替换了 - 从 API 或数据库查出的关联数组结构不一致(有的带
tags键,有的没),直接合并导致部分数据丢失
实操建议:
- 确认需求:真要“堆叠值”?还是只是“后配置优先”?前者选
array_merge_recursive,后者才用array_merge - 别对用户输入或 JSON 解码结果盲目信任——
json_decode($str, true)返回的可能是空数组、null或非数组,传给array_merge会触发警告并返回null - 安全写法:
array_merge((array)$a, (array)$b),强制转数组可避免警告(但注意:数字字符串如"123"转成数组会变[0 => "123"])
要真正“合并同名键的值”,用 array_merge_recursive
array_merge_recursive 是唯一原生支持把相同字符串键的值自动聚合成数组的函数。它遇到同名键时,不覆盖,而是递归地“装进新数组”。
使用场景:
- 合并多个配置数组,希望所有
middleware、routes、providers都保留下来 - 处理多层表单提交数据,不同来源的
files或tags需叠加而非覆盖
示例:
$a = ['tags' => ['php']]; $b = ['tags' => ['mysql', 'laravel']]; $result = array_merge_recursive($a, $b); // 结果:['tags' => ['php', 'mysql', 'laravel']]
注意点:
- 如果某一层的同名键值本身是数组,它会继续递归合并;如果值是字符串或数字,就直接追加到该键对应的数组里
- 数值键(如
[0 => 'x'])行为和array_merge一样:不覆盖,只追加 - 不能处理“混合键型”——比如
['tags' => 'php']和['tags' => ['mysql']]混用,会报 Notice 或产生意外嵌套
非递归场景下想手动合并同名键?用 foreach + is_array 判断
当 array_merge_recursive 过于激进(比如你只想合并某几个特定键,其余仍按覆盖逻辑),就得自己控制。
典型场景:
- 只对
permissions、scopes这类白名单键做叠加,其他键照常覆盖 - 合并前需过滤空值、去重、或做类型转换(如把字符串
"1,2,3"拆成数组再合并)
实操建议:
- 先初始化目标数组:
$merged = $first; - 遍历第二个数组:
foreach ($second as $key => $value) { ... } - 对目标键做判断:
if (in_array($key, ['tags', 'roles'])) { $merged[$key] = array_merge((array)($merged[$key] ?? []), (array)$value); } - 其余键直接赋值:
else { $merged[$key] = $value; }
关键细节:
-
$merged[$key] ?? []防止未定义索引 Notice -
(array)$value统一类型,避免array_merge报错 - 别漏掉
is_array($merged[$key])判断——万一前一个值是字符串,直接array_merge会失败
数字键和字符串键混用时,+ 运算符比 array_merge 更可控
如果你的数组同时含数字索引(如 [0 => 'a', 1 => 'b'])和字符串键(如 ['id' => 123]),又不想让数字键被重排,+ 运算符是更透明的选择。
它不重排、不覆盖、不递归,只做“左优先联合”:
- 左边存在的键,右边同名键直接忽略
- 左边不存在的键,才从右边取
- 数字键也按原样保留,不会变成
0,1,2...
示例:
$a = [0 => 'first', 'name' => 'Alice']; $b = [0 => 'second', 'name' => 'Bob', 'age' => 30]; var_dump($a + $b); // 输出:[0 => 'first', 'name' => 'Alice', 'age' => 30]
容易踩的坑:
-
+不处理嵌套,遇到子数组也不会递归合并 - 如果右边数组有大量需要“覆盖优先”的配置项,
+反而会让旧值残留,此时必须换回array_merge - PHP 8.0+ 对
+的类型推导更严格,若左右操作数之一为null,会报TypeError
真正麻烦的不是选哪个函数,而是没提前确认数组里到底有哪些键、是什么类型、从哪来。尤其从 $_GET、json_decode、DB 查询结果来的数组,结构往往比文档写的松散得多。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











