PHP中+运算符是数组联合而非合并,按左操作数键名优先保留,右操作数同名键被忽略、新增键追加,不重索引不覆盖;适用场景极窄,如字符串键配置补充,覆盖需用array_merge()或array_replace()。

PHP中+运算符对数组的含义不是“合并”而是“键名优先覆盖”
很多人以为+和array_merge()一样,结果发现数值键被丢、重复键没叠加、甚至顺序都乱了。根本原因:PHP里+是**数组联合(union)**,不是加法——它按左操作数的键名逐个取值,右操作数中同名键直接跳过,不覆盖也不重排。
典型错误现象:$a = [0 => 'x', 1 => 'y']; $b = [0 => 'z', 1 => 'w']; var_dump($a + $b); 输出 array(2) { [0]=> string(1) "x" [1]=> string(1) "y" } —— $b 完全没生效。
- 只对**字符串键名**做“左优先保留”,数值键也当字符串处理(但会保持原索引形式)
- 右操作数中所有与左操作数键名相同的元素都被忽略,不管值是什么
- 右操作数的**新增键名**(左操作数没有的)才会追加到结果末尾
- 不会重索引,不会类型转换,不会触发任何回调
什么时候该用+,什么时候必须换array_merge()
用+的合理场景非常窄:你明确想“以左数组为模板,仅补充右数组里左数组没有的配置项”,比如默认配置 + 用户自定义配置,且键全是字符串。
例如:$defaults = ['host' => 'localhost', 'port' => 3306]; $config = ['port' => 3307, 'charset' => 'utf8']; $final = $defaults + $config; → ['host'=>'localhost', 'port'=>3306, 'charset'=>'utf8'],port没被覆盖。
立即学习“PHP免费学习笔记(深入)”;
- 需要覆盖同名键?用
array_merge()(注意:数值键会被重索引) - 要保留数值键且允许覆盖?用
array_replace()(PHP 5.3+) - 要深度合并(多维)?别用
+,得自己递归或用array_replace_recursive() - 想拼接两个数值数组并保持顺序?老实用
array_merge($a, $b),别碰+
+在关联数组和索引数组中的行为差异
表面上看都是“左优先”,但实际表现因键类型不同而容易误判。关键点在于:PHP把纯数字字符串键(如"0")当作整型键处理,但+不重索引,所以结果可能看起来“错位”。
示例:$x = ['a' => 1, 0 => 2]; $y = ['b' => 3, 0 => 4]; var_dump($x + $y); 输出:['a'=>1, 0=>2, 'b'=>3] —— $y[0]被跳过,'b'作为新键追加。
- 字符串键(
'key')严格按名称比对,区分大小写 - 整型键(
0,1)和等价字符串键("0","1")被视为相同键名 - 混合键数组中,
+仍逐个检查键名存在性,不关心键的原始类型 - 如果左数组全是数值键,
+几乎无用——右数组永远无法覆盖或补位,除非你刻意构造稀疏索引
常见陷阱:错误日志里出现Array to string conversion却跟+有关
这通常不是+直接报错,而是你把数组当标量用了,比如:$arr = ['a'=>1] + ['b'=>2]; echo $arr . 'done';。PHP尝试把整个数组转成字符串时触发警告。
更隐蔽的是在条件判断或函数参数中误传:if ($arr1 + $arr2 == []) {...},这种比较永远为false(数组不能直接==空数组),还可能掩盖逻辑错误。
- 永远不要对
+的结果做==或===数组比较,用empty()或count()代替 - 调试时用
var_export()而不是echo或print_r()(后者可能截断深层结构) - CI/CD流程中如果静态分析工具报
Array operation with + may lead to unexpected results,大概率是你本该用array_merge或明确注释意图 - 多人协作时,
+极易被后续修改者误解为“合并”,建议在代码旁加单行注释说明用途,比如// 仅补充缺失键,不覆盖已有配置



















