无法正确生成深层菜单的menu_order值,PHP递归逻辑出现重复数据如何解决
问题核心原因
- 外层遍历了所有菜单项,子节点既会在外层循环被添加,也会在父节点的递归逻辑中被重复添加,导致数据重复、排序混乱
- 没有从根节点(
parent=0)开始遍历,遍历逻辑不符合深度优先的排序要求
修正后可直接运行的示例代码
<?php $posts = [ ['id' => 15, 'parent' => 0, 'menu_order' => 0], ['id' => 22, 'parent' => 15, 'menu_order' => 0], ['id' => 26, 'parent' => 15, 'menu_order' => 0], ['id' => 30, 'parent' => 15, 'menu_order' => 0], ['id' => 47, 'parent' => 22, 'menu_order' => 0], ['id' => 49, 'parent' => 22, 'menu_order' => 0], ['id' => 51, 'parent' => 22, 'menu_order' => 0], ['id' => 68, 'parent' => 26, 'menu_order' => 0], ['id' => 69, 'parent' => 26, 'menu_order' => 0], ]; // 先构建父子映射,方便快速查找某个节点的所有子节点,纯数据库场景可省略这一步 $childrenMap = []; foreach ($posts as $p) { $childrenMap[$p['parent']][] = $p; } $test = []; $currOrder = 0; // 深度优先遍历递归函数 function buildMenuOrder($parentId, &$childrenMap, &$currOrder, &$test) { if (!isset($childrenMap[$parentId])) { return; } foreach ($childrenMap[$parentId] as $item) { $item['menu_order'] = $currOrder; $test[] = $item; $currOrder++; // 递归处理当前节点的所有子节点 buildMenuOrder($item['id'], $childrenMap, $currOrder, $test); } } // 仅从根节点(parent=0)开始遍历 buildMenuOrder(0, $childrenMap, $currOrder, $test); // 打印验证结果 print_r($test);
输出结果
和你期望的效果完全一致:
id | parent | menu_order 15 0 0 22 15 1 47 22 2 49 22 3 51 22 4 26 15 5 68 26 6 69 26 7 30 15 8
纯数据库场景适配
如果不需要提前加载所有菜单数据,直接在递归中查库即可,调整后的递归函数如下:
function buildMenuOrder($parentId, &$currOrder, &$test) { // 查询当前父节点的所有子节点 $childs = $this->where('parent', $parentId) ->get() ->getResult(); foreach ($childs as $c) { $c['menu_order'] = $currOrder; $test[] = $c; $currOrder++; // 递归处理子节点的下级菜单 buildMenuOrder($c['id'], $currOrder, $test); } } // 调用方式 $test = []; $currOrder = 0; buildMenuOrder(0, $currOrder, $test);
内容的提问来源于stack exchange,提问作者sfarzoso
相关产品推荐
相关产品推荐

