You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP如何将带parent_id的扁平数组转换为完整树形结构数组

修复后完整代码
<?php 
$arr = [
    ['id'=> 1, 'parent_id' => '-', 'name' => 'id1'],
    ['id' => 2, 'parent_id' => 1, 'name'=> 'id2' ],
    ['id' => 3, 'parent_id' => 1, 'name'=> 'id3' ],
    ['id' => 4, 'parent_id' => '-', 'name'=> 'id4' ],
    ['id' => 5,'parent_id' => 2, 'name'=> 'id5' ],
    ['id' => 6, 'parent_id' => 3, 'name'=> 'id6' ],
    ['id' => 7, 'parent_id' => '-', 'name'=> 'id7' ],
    ['id' => 8, 'parent_id' => 3, 'name'=> 'id8' ],
    ['id' => 9, 'parent_id' => 4, 'name'=> 'id9' ], 
    ['id' => 10, 'parent_id' => 9, 'name'=> 'id10' ]
];

$new = array();
foreach ($arr as $a){
    $new[$a['parent_id']][] = $a;
}
// 仅修改这一行:原来只传第一个顶级节点,现在传所有parent_id为'-'的顶级节点集合
$tree = createTree($new, $new['-']);
print_r($tree);

function createTree(&$list, $parent){
    $tree = array();
    foreach ($parent as $k=>$l){
        if(isset($list[$l['id']])){
            $l['children'] = createTree($list, $list[$l['id']]);
        }
        $tree[] = $l;
    } 
    return $tree;
}
问题原因

你原来的代码中createTree的递归逻辑本身是正常的,问题出在调用时传入的初始父节点集合:你只传入了array($arr[0]),也就是仅把第一个parent_id = '-'的顶级节点作为根节点处理,剩下的id4、id7两个顶级节点没有被纳入初始遍历范围,自然不会出现在最终的树形结构里。

实现原理解释
  • 节点分组逻辑:你提前用$new数组按parent_id对所有节点做了索引的逻辑非常高效,后续查找任意节点的子节点时,直接通过$new[当前节点id]就能拿到,不需要重复遍历整个扁平数组,整体时间复杂度为O(n)。
  • 递归逻辑:createTree函数会遍历传入的父节点集合,给每个父节点查找对应的子节点,再递归处理子节点的后代,最后把挂载了children字段的节点组装成树返回,逻辑本身不需要修改。
  • 初始传参修正:因为你已经把所有节点按parent_id分组,$new['-']天然就是所有顶级节点的集合,直接把它作为初始父节点集合传入,就能生成包含所有顶级节点的完整多根树结构。

内容的提问来源于stack exchange,提问作者codepnk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.26 12:15:03