
本文介绍如何编写一个支持多层嵌套数组递归合并的 php 函数,使源数组中已存在的键值优先保留,目标数组中新增的键(包括深层子键)自动补全,兼顾简洁性与健壮性。
本文介绍如何编写一个支持多层嵌套数组递归合并的 php 函数,使源数组中已存在的键值优先保留,目标数组中新增的键(包括深层子键)自动补全,兼顾简洁性与健壮性。
在 PHP 开发中,array_merge() 是常用工具,但它仅执行扁平化合并:遇到同名数组键时直接覆盖而非递归合并。当需要“以 $array_1 为基底,用 $array_2 补充缺失的键(含多级嵌套)”时,必须自定义递归逻辑。
以下是一个简洁、可读性强且真正递归的实现:
function array_merge_recursive_fill($base, $defaults) {
$merged = $base; // 以 base 为起点,仅补充 defaults 中缺失的部分
foreach ($defaults as $key => $value) {
// 若 base 中无此 key,或 base[$key] 非数组而 $value 是数组 → 直接覆盖(避免类型冲突)
if (!isset($base[$key]) || !is_array($base[$key]) || !is_array($value)) {
$merged[$key] = $value;
} else {
// 仅当两者均为数组时,递归合并子数组
$merged[$key] = array_merge_recursive_fill($base[$key], $value);
}
}
return $merged;
}✅ 使用示例:
$array_1 = [
'array_key' => [
'array_key_1' => 1,
'array_key_2' => 2,
'array_key_3' => 3,
],
];
$array_2 = [
'array_key' => [
'array_key_1' => null,
'array_key_2' => null,
'array_key_3' => null,
'array_key_4' => null,
'array_key_5' => null,
],
];
$result = array_merge_recursive_fill($array_1, $array_2);
print_r($result);
// 输出符合预期:
// Array (
// [array_key] => Array (
// [array_key_1] => 1
// [array_key_2] => 2
// [array_key_3] => 3
// [array_key_4] => null
// [array_key_5] => null
// )
// )⚠️ 注意事项与最佳实践:
-
类型安全优先:该函数在
base[$key]和value类型不一致(如一为数组一为字符串)时,直接用$value覆盖 —— 这避免了“试图遍历非数组”的警告,也符合“用 defaults 填充缺失结构”的语义。 -
防止无限递归:PHP 数组本身不支持真正的循环引用(除非显式使用引用),但若传入含循环引用的数组(如
$a = [&$a]),本函数仍可能栈溢出。生产环境建议配合spl_object_hash()或第三方库(如symfony/var-dumper的保护机制)做预检。 -
与原生函数区分命名:推荐使用
array_merge_recursive_fill或array_fill_recursive等清晰名称,避免与array_merge_recursive()混淆(后者是“深度合并”,而非“以 base 为主、defaults 为补丁”)。 -
扩展性提示:如需支持更多策略(如“仅填充 null/empty 值”,或“跳过特定键”),可在函数中增加
$options参数,以回调或位掩码形式控制行为。
总结:一个健壮的递归数组填充函数,核心在于明确合并语义(主从关系)、严格判断数组类型、并利用函数自身实现自然递归。它比手动多层 foreach 更简洁,比盲目覆盖更安全,是配置合并、默认值注入等场景的理想工具。

















