← PHP array_map() 函数:批量处理数组元素的实用工具 PHP array_merge_recursive() 函数:递归合并数组,键冲突不再简单覆盖 →

PHP array_merge()函数:合并数组时键名冲突怎么处理

著
原创 2026-10-08 PHP 已有人查阅

一、array_merge()的定位

PHP内置的array_merge()函数,用来把一个或多个数组的元素合并成一个数组。它从PHP4.0开始就有了,是数组操作里出场率比较高的一个。

语法形式:

array array_merge(array $array1 [, array $...]);

$array1是必须的,后面可以跟任意多个数组,都是可选的。返回值就是合并后的数组。

这个函数的用法看着简单,但真正容易出问题的地方在键名处理上。很多人第一次用array_merge()踩坑,都是因为没搞清楚字符串键和数字键在合并时的行为不一样。

官方文档给了一句提示:如果两个或多个数组元素有相同的键,之后一个会覆盖前面的。这句话只说对了一半,准确说,这条规则只适用于字符串键。数字键是另一套逻辑,下面会分开讲。

二、字符串键:后面的覆盖前面的

先看字符串键的情况,用代码号学习编程的示例来说明:

<?php
$game1 = array("a" => "cricket", "b" => "hockey");
$game2 = array("c" => "football", "b" => "tennis");
print_r(array_merge($game1, $game2));
?>

输出:

Array ( [a] => cricket [b] => tennis [c] => football )

两个数组都有b这个键。$game1里b是hockey,$game2里b是tennis。合并后b的值变成了tennis,也就是后一个数组的值把前一个覆盖掉了。a和c没有冲突,各自保留。

这就是字符串键的规则:键名相同就覆盖,位置靠后的赢。

项目开发里这个特性有它的用处。比如你有一个默认配置数组,再传一个用户配置数组进来,用array_merge($default,$user)就能让用户配置覆盖默认值,写法很干净。这是array_merge()在配置合并场景下的典型用法,比手写循环判断要省事。

但反过来,如果你不希望覆盖,就得换别的函数,比如array_merge_recursive(),它会把冲突的键值合并成数组,而不是简单覆盖。这两个函数的差异,选型时要想清楚。

三、数字键:不覆盖,重新编号

数字键的行为和字符串键不同。看这个例子:

<?php
$a = [1, 2, 3, 4];
$b = [5, 6, 7, 8];
print_r(array_merge($a, $b));
?>

输出:

Array ( [0] => 1 [1] => 2 [2] => 3 [3] => 4 [4] => 5 [5] => 6 [6] => 7 [7] => 8 )

两个数组的键都是0、1、2、3,按理说会冲突。但合并后并没有覆盖,而是把$b的值接在$a后面,键从0开始重新编号,一直排到7。

这就是数字键的规则:不覆盖,重新索引。array_merge()会把所有数字键的值按顺序追加,然后从0开始重新分配键名。

再看一个键名不连续的例子:

<?php
$a1 = array(1 => "java", 6 => "T", 4 => "point");
$res = array_merge($a1);
print_r($res);
?>

输出:

Array ( [0] => java [1] => T [2] => point )

原本键是1、6、4,合并后变成0、1、2。哪怕只传一个数组,数字键也会被重新编号。这一点容易忽略,如果你合并后还要按原来的键取值,就会出问题。

我个人的经验是:处理索引数组时,把array_merge()当成"拼接并重排"来看,不要指望它保留原来的键。如果键名有意义、必须保留,那就得用+运算符或者array_replace(),它们的行为和array_merge()不一样。

四、混合键名的合并

实际数据里,字符串键和数字键经常混在一起。看这个例子:

<?php
$cric1 = array("sachin" => "18426", 15921, 200);
$cric2 = array("virat", "ganguly", "sachin" => "arjun", "yuvraj" => "world cup", 2011);
$res = array_merge($cric1, $cric2);
print_r($res);
?>

输出:

Array (
    [sachin] => arjun
    [0] => 15921
    [1] => 200
    [2] => virat
    [3] => ganguly
    [yuvraj] => world cup
    [4] => 2011
)

拆开看这个结果:

sachin是字符串键,两个数组都有,后面的arjun覆盖了前面的18426。

yuvraj是字符串键,只在$cric2里有,直接保留。

15921和200在$cric1里是数字键,virat、ganguly、2011在$cric2里也是数字键。这些数字键的值合并后按顺序重排,键从0开始分配。

所以最终结果里,字符串键sachin和yuvraj保留了自己的键名,数字键全部重排成0到4。

这个例子比较典型地展示了array_merge()的完整行为。理解了它,基本就掌握了这个函数的核心。

五、和+运算符的区别

说到数组合并,绕不开+运算符。两者经常被拿来比较,但行为差别不小。

+运算符的规则是:键名相同就保留左边的,忽略右边的。它不看键是字符串还是数字,一视同仁。

<?php
$a = array("x" => 1, "y" => 2);
$b = array("x" => 3, "z" => 4);
print_r($a + $b);
?>

输出:

Array ( [x] => 1 [y] => 2 [z] => 4 )

x冲突了,+保留了$a里的1,而不是$b里的3。这和array_merge()的"后者覆盖"正好相反。

所以选择的时候要看你的意图:

想让后面的数组覆盖前面的,用array_merge()。

想让前面的数组优先、不被覆盖,用+。

需要保留数字键原样,用+或者array_replace()。

我见过不少代码用+来合并配置,其实意图是"用户配置覆盖默认配置",结果因为+的规则反了,默认值把用户值挡住了。这类bug不报错,只是结果不对,排查起来挺费劲。所以合并配置时,我一般倾向于明确用array_merge()。

六、本节课程知识要点

  • array_merge()合并一个或多个数组,返回新数组。

  • 字符串键冲突时,后面的覆盖前面的。

  • 数字键不覆盖,按顺序追加后从0重新编号。

  • 哪怕只传一个数组,数字键也会被重新编号。

  • 混合键名时,字符串键按覆盖规则处理,数字键按重排规则处理。

  • +运算符保留左边的值,和array_merge()的覆盖方向相反。

  • 配置合并想要覆盖效果,用array_merge();想保留原键,考虑+或array_replace()。

  • 需要递归合并冲突键时,看array_merge_recursive()。

← PHP array_map() 函数:批量处理数组元素的实用工具 PHP array_merge_recursive() 函数:递归合并数组,键冲突不再简单覆盖 →
分享笔记 (共有 篇笔记)
验证码:
微信公众号