导读:本期聚焦于小伙伴创作的《PHP数组变量如何合并?盘点array_merge与加号运算符的区别和用法》,敬请观看详情。把两个PHP数组变量拼到一起时,有人用array_merge,有人直接用加号,结果却大相径庭。核心差异在于字符串键名冲突时的处理:array_merge会让后面数组的值覆盖前面,而加号运算符保留前面数组已有键的值。数字键在array_merge中会被重新索引,加号则原样保留。实际写配置合并、请求参数整合时,选错方式会导致数据被意外覆盖或丢失。下面通过具体代码对比两种写法在关联数组和索引数组下的返回结果,并说明在递归合并多维数组时该用什么函数,帮你避开键值处理的坑。

在PHP开发中,把多个数组变量合并成一个数组是极其常见的操作。无论是合并配置项、整合表单数据,还是组装接口返回结构,我们都会面对“如何合并”的选择。PHP提供了多种数组合并手段,其中最容易被混淆的就是array_merge函数与加号(+)运算符。它们表面上都能把数组连起来,但在键名处理逻辑上有本质不同。

一、array_merge函数的基本用法

array_merge是PHP内置的数组函数,用来将一个或多个数组的单元合并起来。它接收一个或多个数组参数,返回合并后的新数组。对于字符串键名(关联数组),如果后面的数组中有相同键名,那么后面的值会覆盖前面的;对于数字键名(索引数组),所有元素会被按顺序追加,并且重新从0开始建立连续的数字索引。

下面是一段基础示例,展示关联数组与索引数组在array_merge下的表现:

<?php
$configA = array(
    'host' => '127.0.0.1',
    'port' => 3306,
    'debug' => false
);

$configB = array(
    'port' => 3307,
    'user' => 'root'
);

$merged = array_merge($configA, $configB);
print_r($merged);
// 输出:
// Array (
//     [host] => 127.0.0.1
//     [port] => 3307   // 后面的覆盖前面的
//     [debug] => false
//     [user] => root
// )

$listA = array('a', 'b');
$listB = array('c', 'd');
$listMerged = array_merge($listA, $listB);
print_r($listMerged);
// 输出:Array ( [0] => a [1] => b [2] => c [3] => d )
?>

从上面可以看出,array_merge对字符串键采取“后者覆盖前者”的策略,对数字键则重新编号。这种特性在合并用户配置与默认配置时非常实用,因为通常希望用户传进来的配置项生效。

不过要注意,如果传入的数组本身不是数组类型(比如null),array_merge会把null当作空数组处理,不会报错;但如果传入的是标量值则会产生警告。因此在使用前最好用is_array做一下校验,或者确保变量一定是数组。

二、加号运算符的合并逻辑

PHP中的加号(+)也可以用于数组合并,但它的语义和array_merge完全不同。加号运算的规则是:以左侧数组为基础,右侧数组中的元素只有在左侧数组中不存在对应键名时才会被加入。也就是说,左侧数组的键值具有更高优先级,不会被右侧覆盖。

我们用和前面一样的关联数组来做对比:

<?php
$configA = array(
    'host' => '127.0.0.1',
    'port' => 3306,
    'debug' => false
);

$configB = array(
    'port' => 3307,
    'user' => 'root'
);

$added = $configA + $configB;
print_r($added);
// 输出:
// Array (
//     [host] => 127.0.0.1
//     [port] => 3306   // 保留左侧的,未被覆盖
//     [debug] => false
//     [user] => root   // 左侧没有的键才加进来
// )

$listA = array('a', 'b');
$listB = array('c', 'd');
$listAdded = $listA + $listB;
print_r($listAdded);
// 输出:Array ( [0] => a [1] => b )
// 数字键0和1已存在于左侧,因此右侧的不会被添加
?>

可以看到,加号运算符对数字索引数组几乎“无合并效果”,因为索引0、1在左侧已存在,右侧的值全部被忽略。这一点经常让初学者感到意外,以为加号也能像array_merge那样拼接列表,其实并不能。

加号更适合用来设置“默认值”场景:把用户选项放在左边,默认选项放在右边,用户没填的才用默认的。但如果你需要把两个索引列表拼起来,加号是错误选择。

三、两者核心差异对比

为了更直观地理解,我们把两种方式的差异整理成表格:

对比维度array_merge加号运算符
字符串键冲突后面覆盖前面前面保留,后面忽略
数字键处理重新索引,顺序追加键已存在则忽略右侧
典型用途用户配置覆盖默认配置默认配置补充用户缺失项
多维数组一维合并,不递归一维合并,不递归

从表中能清楚看到,两者不是简单的“语法糖替换”关系,而是语义不同的操作。在代码评审中,如果看到有人用加号去合并两个索引数组,基本可以判定这是一个bug。

此外,当数组合并涉及多维结构时,无论是array_merge还是加号,都只会合并第一层。子数组会被整体覆盖或保留,而不会逐字段合并。这时就需要递归合并函数。

四、多维数组的递归合并

如果数组是多维的,比如默认配置里包含数据库子配置,用户配置只改了其中一项,我们希望子配置也能按字段合并,那么应该使用array_merge_recursive,或者自己写递归逻辑。array_merge_recursive会把同名字符串键下的值合并成数组,但有时会产生意料之外的嵌套,因此更可控的做法是手动实现递归覆盖。

示例:使用自定义函数实现“后者覆盖前者”的递归合并

<?php
function deep_merge($base, $override) {
    if (!is_array($base)) {
        return $override;
    }
    foreach ($override as $key => $value) {
        if (is_array($value) && isset($base[$key]) && is_array($base[$key])) {
            $base[$key] = deep_merge($base[$key], $value);
        } else {
            $base[$key] = $value;
        }
    }
    return $base;
}

$default = array(
    'db' => array('host' => '127.0.0.1', 'port' => 3306),
    'cache' => true
);
$user = array(
    'db' => array('port' => 3307)
);

$result = deep_merge($default, $user);
print_r($result);
// 输出:db.host保留127.0.0.1,db.port变成3307,cache为true
?>

这种写法比array_merge_recursive更安全,因为它不会把同键下的标量值变成数组,而是直接覆盖。在框架配置加载、环境变量合并等场景中非常实用。

总结来说,PHP数组合并没有唯一正确答案,关键看业务语义:要覆盖就用array_merge或递归覆盖,要保底就用加号。理解键名处理规则,才能写出符合预期的数据整合代码。

PHP数组合并array_merge加号运算符修改时间:2026-08-11 13:39:46

免责声明:​ 已尽一切努力确保本网站所含信息的准确性。网站内容多为原创整理与精心编撰,观点力求客观中立。本站旨在免费分享,内容仅供个人学习、研究或参考使用。若引用了第三方作品,版权归原作者所有。如内容涉及您的权益,请联系我们处理。
内容垂直聚焦
专注技术核心技术栏目,确保每篇文章深度聚焦于实用技能。从代码技巧到架构设计,为用户提供无干扰的纯技术知识沉淀,精准满足专业提升需求。
知识结构清晰
覆盖从开发到部署的全链路。AI、前端、编程、数据库、服务器、建站、系统层层递进,构建清晰学习路径,帮助用户系统化掌握开发与运维所需的核心技术。
深度技术解析
拒绝泛泛而谈,深入技术细节与实践难点。无论是数据库优化还是服务器配置,均结合真实场景与代码示例进行剖析,致力于提供可直接应用于工作的解决方案。
专业领域覆盖
精准对应开发生命周期。从前端界面到后端编程,从数据库操作到服务器运维,形成完整闭环,一站式满足全栈工程师和运维人员的技术需求。
即学即用高效
内容强调实操性,步骤清晰、代码完整。用户可根据教程直接复现和应用于自身项目,显著缩短从学习到实践的距离,快速解决开发中的具体问题。
持续更新保障
专注既定技术方向进行长期、稳定的内容输出。确保各栏目技术文章持续更新迭代,紧跟主流技术发展趋势,为用户提供经久不衰的学习价值。