PHP递归返回数组时应使用array_merge()而非+合并,因+会静默丢弃右侧同名键;需显式处理空数组终止条件,避免引用传参导致状态污染,确保每层返回结构清晰。

递归返回数组时直接用 + 合并会丢键
PHP 中数组加法操作符 + 是“左侧优先”的键合并,不是真正的合并。如果递归中每个分支返回一个带字符串键的数组(比如 ['id' => 1, 'name' => 'a']),用 $a + $b 会导致右侧数组中与左侧同名的键被完全忽略——这看起来像“合并失败”,其实是语义误解。
常见错误现象:array_merge() 没用、递归结果只有一层、某些子节点数据消失。
- 用
+合并关联数组 → 键冲突时静默丢弃右值 - 用
array_merge($a, $b)→ 正确合并,数值键重排,字符串键保留 - 递归场景下,应始终用
array_merge(...$results)或循环调用array_merge($acc, $next)
array_merge() 在递归中必须显式接收所有子结果
很多人写递归时习惯这样:
function getTree($nodes) {
$result = [];
foreach ($nodes as $node) {
$children = getTree($node['children']);
$result[] = array_merge($node, $children); // ❌ 错:把整个子数组当单个值合并
}
return $result;
}
这里 array_merge($node, $children) 把 $children(通常是数组)当成一个普通参数压进 $node 的键里,而不是展开合并。真正要的是把子树结果“拼到当前层级的 children 字段里”或“平铺到顶层”。
立即学习“PHP免费学习笔记(深入)”;
- 若想保持嵌套结构:直接赋值
$node['children'] = $children; - 若想扁平合并所有节点:用
$result = array_merge($result, [$node], $children); - 注意
array_merge()不接受单个数组变量作为可变参数,需用...展开或循环累积
递归未设终止条件或初始值导致空数组吞掉结果
典型表现:输入非空,但函数返回 [];或者深层递归后只返回最后一层数据。根本原因常是:递归调用前没检查是否还有子节点,或初始化 $result = [] 放错了位置(比如放在循环内)。
- 终止条件缺失 → 触发 PHP 最大递归深度限制,报
Fatal error: Maximum function nesting level - 子节点为空时仍执行递归调用 → 返回空数组,但后续没做判空处理,导致
array_merge([], [])看似“没变化”,实则掩盖逻辑断点 - 推荐写法:
if (empty($nodes)) return [];显式兜底,比依赖隐式返回更可控
引用传参或全局变量干扰递归独立性
为“省事”把结果数组用引用传入递归函数,或在函数内修改全局数组,会导致各层递归互相污染。例如:
function buildList(&$result, $nodes) {
foreach ($nodes as $n) {
$result[] = $n;
buildList($result, $n['children']); // ❌ 所有层级共用同一 $result
}
}
这种写法看似简洁,但无法单独复用、难以测试,且一旦中间出错(如某个分支抛异常),$result 状态已不可逆。
- 纯函数风格更安全:每层递归返回新数组,由上层决定如何合并
- 避免
&$arr参数,除非明确需要性能优化且能控制副作用 - 调试时打印每层返回值,比盯全局变量更容易定位哪一层“吐出了空数组”
array_merge 和 [] 赋值里,漏掉一个就全乱。



















