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": "" } ] } ]
问题分析与修复方案
核心错误点
- $chld数组未重置:每次外层循环时,
$chld没有清空,导致子元素不断累积,最终出现大量重复数据。 - 子元素数据错误:内层循环错误使用外层
$row的字段生成子元素,应该用当前子节点的$row1数据。 - 层级关联逻辑错误:没有正确将子节点挂载到对应父节点下,而是给每个节点都附加了所有子元素,完全不符合嵌套逻辑。
优化后的代码
// 一次性获取所有层级数据,避免多次数据库查询 $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
相关产品推荐
相关产品推荐

