array_merge要求所有参数必须是数组,传入null、字符串、整数等非数组类型会触发Warning;数字键会被重排追加,字符串键后者覆盖前者;性能差在每次全量拷贝与重索引,大批量应避免循环合并。

array_merge 合并空数组或非数组会报错吗
会,而且很常见——array_merge 要求所有参数都必须是数组,传入 null、string、int 或未定义变量时,直接触发 Warning:array_merge(): Expected parameter 1 to be an array, X given。
实际场景里,比如从 API 拿回的数据结构不稳定,$data['tags'] 有时是数组,有时是 null,直接 array_merge($a, $data['tags']) 就崩了。
- 务必提前过滤:用
is_array()判断再合并,别依赖“它应该是个数组” - 可封装一层安全合并函数,例如:
array_merge(...array_filter([$a, $b, $c], 'is_array')) - 注意
array_merge([])是合法的,但array_merge()(零参数)会报错,PHP 8.1+ 才允许
键名重复时 array_merge 怎么处理数字键和字符串键
行为完全不同:数字键(纯整数)会被重排并追加,字符串键(包括 "0" 这种字符串数字)则后者覆盖前者。
比如:array_merge(['a' => 1, 'b' => 2], ['b' => 3, 'c' => 4]) 结果是 ['a' => 1, 'b' => 3, 'c' => 4];而 array_merge([1, 2], [3, 4]) 得到 [1, 2, 3, 4]。
立即学习“PHP免费学习笔记(深入)”;
- 别指望保留原始数字键顺序——
array_merge强制重索引,哪怕你传的是[0 => 'x', 2 => 'y'],结果也是[0 => 'x', 1 => 'y']</li> <li>要保留键名(尤其关联数组合并),改用 <code>+
运算符:$a + $b,但注意它只取左操作数中不存在的键,不覆盖也不重排 -
array_replace更适合“覆盖式合并”,它按键名替换,且支持多维,但不会递归
合并大数组时 array_merge 性能差在哪
核心问题:每次调用都做完整拷贝 + 重索引,时间复杂度 O(n+m),内存开销翻倍。10 万条数据合并一次,可能瞬间吃掉几 MB 内存,还拖慢响应。
不是说不能用,而是得看场景——如果只是拼接配置项(几十个元素),完全没问题;但要是循环里反复 array_merge($acc, $chunk),就是典型性能陷阱。
- 避免在 foreach 中累积合并:
$result = [];$result = array_merge($result, $item);→ 改用array_push(...)或直接$result[] = ... - 大批量合并优先考虑生成器或迭代器,而不是一次性载入所有数组再 merge
- PHP 7.4+ 可用展开语法:
[...$a, ...$b],语义更清晰,性能略优,但同样不处理键冲突逻辑
array_merge_recursive 和普通 merge 的关键区别
唯一区别:遇到相同字符串键时,array_merge_recursive 把值“装进新数组”,而不是覆盖或丢弃。但它不智能识别类型——两个字符串同名键,也会被包成数组,常导致意外嵌套。
示例:array_merge_recursive(['name' => 'A'], ['name' => 'B']) 返回 ['name' => ['A', 'B']];但如果一个是字符串、一个是数组,结果会是 ['name' => ['A', [...]]],很难预测。
- 它不递归合并数字键,行为和
array_merge一致(重排) - 真正需要深度合并(比如配置数组逐层覆盖+追加),得用
array_replace_recursive,或自己写递归逻辑 - 别把它当“安全版 merge”用——它解决的是特定场景,不是容错方案
最易被忽略的一点:array_merge 对 null 值本身不做特殊处理,但如果你合并的数组里有 null 键(PHP 允许),它会被当成字符串 "null" 处理,而不是跳过——这种边界情况,调试时很难一眼发现。











