如何用PHP将数据库查询返回的数组转换为树形结构
PHP 数组转指定树形结构实现方案
问题说明
我用PHP开发,数据库查询返回一个数组,需要根据其中的dropdown_id(层级节点标识)和dropdown_where(父节点关联标识)转换为指定的树形结构,推测需要用递归函数,但不清楚具体实现方式,求实现方法和方案建议。
原始数组
$originalArray = [ [ 'nome' => 'adicionar', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => '', 'tipo_sub_funcao' => 3, 'check_dropdown' => '', 'posicao' => 1, 'dropdown_id' => 1, 'dropdown_where' => '', 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'drop teste 1', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'teste', 'tipo_sub_funcao' => 3, 'check_dropdown' => '', 'posicao' => 5, 'dropdown_id' => '1.1', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'deletar', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_deletar[sub_funcao]', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 3, 'dropdown_id' => 3, 'dropdown_where' => '', 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'editar', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_editar[sub_funcao]', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 2, 'dropdown_id' => 2, 'dropdown_where' => '', 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao teste 1', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'teste', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 4, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao teste 2', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'teste', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 1, 'dropdown_id' => '', 'dropdown_where' => '1.1', 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_adicionar[sub_funcao]', 'tipo_sub_funcao' => 1, 'check_dropdown' => 'adicionar', 'posicao' => 1, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao dropdown', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_adicionar[sub_funcao_dropdown]', 'tipo_sub_funcao' => 1, 'check_dropdown' => 'adicionar', 'posicao' => 3, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao tab', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_adicionar[sub_funcao_tab]', 'tipo_sub_funcao' => 1, 'check_dropdown' => 'adicionar', 'posicao' => 2, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ] ];
期望输出
$expectedTree = [ [ 'nome' => 'adicionar', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => '', 'tipo_sub_funcao' => 3, 'check_dropdown' => '', 'posicao' => 1, 'dropdown_id' => 1, 'dropdown_where' => '', 'pagina' => 'ddc_funcoes', 'sub_funcao_arr' => [ [ 'nome' => 'sub funcao', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_adicionar[sub_funcao]', 'tipo_sub_funcao' => 1, 'check_dropdown' => 'adicionar', 'posicao' => 1, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao dropdown', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_adicionar[sub_funcao_dropdown]', 'tipo_sub_funcao' => 1, 'check_dropdown' => 'adicionar', 'posicao' => 3, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao tab', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_adicionar[sub_funcao_tab]', 'tipo_sub_funcao' => 1, 'check_dropdown' => 'adicionar', 'posicao' => 2, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'sub funcao teste 1', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'teste', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 4, 'dropdown_id' => '', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'drop teste 1', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'teste', 'tipo_sub_funcao' => 3, 'check_dropdown' => '', 'posicao' => 5, 'dropdown_id' => '1.1', 'dropdown_where' => 1, 'pagina' => 'ddc_funcoes', 'dropdown' => [ [ 'nome' => 'sub funcao teste 2', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'teste', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 1, 'dropdown_id' => '', 'dropdown_where' => '1.1', 'pagina' => 'ddc_funcoes' ] ] ] ] ], [ 'nome' => 'editar', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_editar[sub_funcao]', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 2, 'dropdown_id' => 2, 'dropdown_where' => '', 'pagina' => 'ddc_funcoes' ], [ 'nome' => 'deletar', 'sub_funcao' => 'sub_funcao', 'nome_funcao' => 'funcoes_deletar[sub_funcao]', 'tipo_sub_funcao' => 1, 'check_dropdown' => '', 'posicao' => 3, 'dropdown_id' => 3, 'dropdown_where' => '', 'pagina' => 'ddc_funcoes' ] ];
实现代码
步骤1:按父节点分组
先把所有节点按dropdown_where分组,避免递归中重复遍历原数组,提升效率:
// 分组:键是父节点的dropdown_id(顶级节点用root标识),值是子节点列表 $grouped = []; foreach ($originalArray as $item) { $parentId = $item['dropdown_where'] ?: 'root'; if (!isset($grouped[$parentId])) { $grouped[$parentId] = []; } $grouped[$parentId][] = $item; }
步骤2:递归构建树形结构
编写递归函数,处理每个节点并添加对应的子节点,同时按posicao排序保证顺序:
function buildTree($nodes, $grouped) { $tree = []; foreach ($nodes as $node) { $currentNode = $node; $nodeId = $node['dropdown_id']; // 获取当前节点的所有子节点 $children = $grouped[$nodeId] ?? []; $subFuncaoArr = []; foreach ($children as $child) { $childNode = $child; // 如果子节点有dropdown_id,递归处理它的子节点并放入dropdown字段 if (!empty($child['dropdown_id'])) { $childDropdown = $grouped[$child['dropdown_id']] ?? []; if (!empty($childDropdown)) { $childNode['dropdown'] = buildTree($childDropdown, $grouped); } } $subFuncaoArr[] = $childNode; } // 按posicao排序子节点 usort($subFuncaoArr, function($a, $b) { return $a['posicao'] - $b['posicao']; }); if (!empty($subFuncaoArr)) { $currentNode['sub_funcao_arr'] = $subFuncaoArr; } $tree[] = $currentNode; } // 顶级节点按posicao排序 usort($tree, function($a, $b) { return $a['posicao'] - $b['posicao']; }); return $tree; } // 获取顶级节点并构建树形结构 $topNodes = $grouped['root'] ?? []; $resultTree = buildTree($topNodes, $grouped); // 输出结果查看 echo '<pre>'; print_r($resultTree); echo '</pre>';
方案建议
- 分组优化:先按父节点ID分组,将时间复杂度从O(n²)降至O(n log n)(主要为排序开销),大幅提升处理效率。
- 排序逻辑:在递归过程中按
posicao字段排序,保证输出顺序与期望一致;也可在数据库查询时直接按dropdown_where和posicao排序,减少PHP端处理。 - 空值处理:注意判断
dropdown_id和dropdown_where的空值情况,避免数组索引错误。 - 数据量优化:若数据量较大,可考虑使用嵌套集合模型等树形数据存储方案,优化数据库查询和结构转换逻辑。
内容的提问来源于stack exchange,提问作者lucca.germano
相关产品推荐
相关产品推荐

