PHP合并数组时相同键默认覆盖,需保留双值则应将冲突键的值转为数组;可用array_merge_recursive快速处理字符串键,或手动遍历、array_reduce等自定义逻辑精准控制。

PHP 合并数组时遇到相同键,默认会覆盖(如 array_merge、+ 运算符),想保留两个值,核心思路是:**不直接覆盖,而是将冲突键的值转为数组(或其它结构)来收纳多个值**。
用 array_merge_recursive 处理简单场景
它对相同字符串键会递归合并成数组,数值键则追加。适合值类型一致、无需自定义逻辑的情况:
$a = ['name' => 'Alice', 'age' => 25]; $b = ['name' => 'Bob', 'city' => 'Beijing']; $result = array_merge_recursive($a, $b); // 结果:['name' => ['Alice', 'Bob'], 'age' => 25, 'city' => 'Beijing']
⚠️ 注意:如果原值已是数组,会继续嵌套;不能区分“谁先谁后”,也不支持对数值键做类似处理。
手动遍历合并,完全控制逻辑
最灵活的方式:遍历第二个数组,逐个检查键是否存在,按需合并:
立即学习“PHP免费学习笔记(深入)”;
- 若键不存在 → 直接赋值
- 若键已存在 → 将原值和新值一起装进数组(可去重、排序或加时间戳等)
function mergeKeepBoth($arr1, $arr2) {
$result = $arr1;
foreach ($arr2 as $k => $v) {
if (isset($result[$k])) {
// 已存在,转为数组并追加
if (!is_array($result[$k])) {
$result[$k] = [$result[$k]];
}
$result[$k][] = $v;
} else {
$result[$k] = $v;
}
}
return $result;
}
$a = ['id' => 100, 'tag' => 'php'];
$b = ['id' => 200, 'tag' => 'web'];
var_dump(mergeKeepBoth($a, $b));
// ['id' => [100, 200], 'tag' => ['php', 'web']]
用 array_reduce 或自定义回调增强可扩展性
适合需要统一规则(如所有冲突键都转为唯一数组、或只保留前两个值)的批量操作:
$merged = array_reduce(
[$a, $b],
function ($carry, $item) {
foreach ($item as $k => $v) {
if (!isset($carry[$k])) {
$carry[$k] = $v;
} elseif (!is_array($carry[$k])) {
$carry[$k] = [$carry[$k], $v];
} else {
$carry[$k][] = $v;
}
}
return $carry;
},
[]
);
注意数值键(数字索引)的特殊行为
PHP 中数值键在 array_merge 中总是重新索引,不会冲突;但用 + 时左边数组的数值键会保留,右边同索引的被忽略。如需保留两边数值键的所有值,必须手动处理或改用字符串键:
- 避免用纯数字键做合并依据
- 若必须处理,提前用
array_values()重置索引再合并,或用array_merge($a, $b)直接追加
不复杂但容易忽略的是:没有“开箱即用”的函数能完美满足所有保留需求,关键在于根据数据结构和业务意图选择合并策略——要么用 array_merge_recursive 快速兜底,要么手写循环精准控制。



















