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

PHP中如何实现数组嵌套?层级数据库数据组装问题求助

层级数据组装问题

我需要将数据库中获取的层级数据组装成嵌套数组,但当前代码逻辑错误,输出结果重复数百行,无法得到正确的嵌套结构。

数据库结构

表option_unit存储层级组织数据,包含字段:id(节点ID)、title(节点名称)、parent(父节点ID)、level(层级),数据为CEO(顶级节点,parent为0)→ Accountant(父节点为CEO的ID)→ Manager(父节点为Accountant的ID)、CEO→HR(父节点为CEO的ID)这类层级关系。

现有PHP代码

$stmt=$mysqli->prepare("select * from option_unit order by level asc");
$stmt->execute();
$res=$stmt->get_result();           
while($row=$res->fetch_assoc()){
    $_parent=$row['parent'];            
            //child
            $_chl=$mysqli->prepare("select * from option_unit where parent=?");
            $_chl->bind_param('i',$_parent);
            $_chl->execute();
            $res1=$_chl->get_result();
            while($row1=$res1->fetch_assoc()){
                $chld[]=array("head"=>$row['title'],"id"=>$row['id'],"contents"=>$row['title'],"children"=>"");
            }                   
            $_chl->close();                 
            
            $data[]=array("head"=>$row['title'],"id"=>$row['id'],"contents"=>$row['title'],"children"=>$chld);
    
        }//while

$stmt->close();
echo json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);

当前错误结果

输出的JSON包含数百条重复数据,完全无法形成正确的嵌套层级结构。

期望输出

[
    {
        "head": "CEO",
        "id": 24,
        "contents": "CEO",
        "children": [
            {
                "head": "Accountant",
                "id": 2,
                "contents": "CEO",
                "children": [{ "head": "Manager", "id": "25", "contents": "Mr.Bill" }]
            },
            {
                "head": "HR",
                "id": 9,
                "contents": "CEO",
                "children": ""
            }
        ]
    }
]

问题分析与修复方案

核心错误点

  1. $chld数组未重置:每次外层循环时,$chld没有清空,导致子元素不断累积,最终出现大量重复数据。
  2. 子元素数据错误:内层循环错误使用外层$row的字段生成子元素,应该用当前子节点的$row1数据。
  3. 层级关联逻辑错误:没有正确将子节点挂载到对应父节点下,而是给每个节点都附加了所有子元素,完全不符合嵌套逻辑。

优化后的代码

// 一次性获取所有层级数据,避免多次数据库查询
$stmt = $mysqli->prepare("select * from option_unit order by level asc");
$stmt->execute();
$res = $stmt->get_result();

$allNodes = [];
$tree = [];

// 第一步:将所有数据存入以ID为键的数组,保留父节点ID用于后续关联
while ($row = $res->fetch_assoc()) {
    $allNodes[$row['id']] = [
        "head" => $row['title'],
        "id" => $row['id'],
        "contents" => $row['title'],
        "children" => [],
        "parent" => $row['parent']
    ];
}

// 第二步:构建树形结构,将子节点挂载到对应父节点下
foreach ($allNodes as $id => &$node) {
    $parentId = $node['parent'];
    if ($parentId == 0 || !isset($allNodes[$parentId])) {
        // 顶级节点(父节点为0或不存在)直接加入根数组
        $tree[] = &$node;
    } else {
        // 将当前节点添加到父节点的children数组中
        $allNodes[$parentId]['children'][] = &$node;
    }
    // 移除parent字段,避免输出到JSON
    unset($node['parent']);
}

// 第三步:将空的children数组转为空字符串,匹配期望输出格式
$processEmptyChildren = function(&$nodes) use (&$processEmptyChildren) {
    foreach ($nodes as &$item) {
        if (empty($item['children'])) {
            $item['children'] = "";
        } else {
            // 递归处理子节点的children
            $processEmptyChildren($item['children']);
        }
    }
};
$processEmptyChildren($tree);

$stmt->close();
echo json_encode($tree, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);

代码说明

  • 一次性查询:减少数据库IO操作,提升效率,尤其数据量大时更明显。
  • ID映射数组:通过$allNodes快速查找父节点,避免循环遍历查找,提升组装效率。
  • 递归处理空children:确保所有没有子节点的元素,children字段为字符串"",完全匹配你的期望输出。
  • 引用传递:使用&修改数组元素,确保子节点正确关联到父节点,避免数据拷贝错误。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 05:17:34