多级菜单仅统计前两级:基于menu表的代码实现咨询
关于多级菜单前两级实现的分析与优化建议
首先直接给结论:你当前的代码确实能够实现仅保留前两级菜单的需求,但存在可以优化的地方,包括性能和代码健壮性方面。
现有代码的工作逻辑
你的Controller代码通过两次判断来构建菜单:
- 把
id_parent=0的菜单(一级菜单)直接存入结果数组 - 把其他菜单(二级及以上)尝试挂载到对应父ID的菜单下作为子节点
但这里有个潜在问题:如果菜单存在三级及以上层级(比如某个二级菜单还有子节点),那么在处理三级菜单时,由于结果数组的键只有一级菜单的ID,会触发PHP的未定义索引警告,而且这些三级菜单会被直接丢弃(不会出现在最终结果里)。不过从需求来看,我们本来就不需要三级及以上,所以最终输出的结果确实是前两级,但代码不够健壮。
另外,Model里的SQL查询了所有菜单数据,包括不需要的三级及以上,这会造成不必要的数据库资源浪费,尤其是当菜单数据量较大时。
优化方案
1. 优化SQL查询,只获取前两级数据
既然只需要前两级,我们可以直接在SQL里筛选出一级和二级菜单,避免加载多余数据:
public function getMenu() { $sql = "SELECT m.* FROM menu m WHERE m.id_parent = 0 OR m.id_parent IN (SELECT id FROM menu WHERE id_parent = 0)"; return $this->db->query($sql); }
这个SQL会先找出所有一级菜单(id_parent=0),再找出所有父ID属于一级菜单的二级菜单,只返回这两类数据。
2. 优化Controller逻辑,提升健壮性
把一级菜单和二级菜单的处理分开,避免未定义索引的问题,逻辑也更清晰:
public function adminNavMenu() { $this->data['menu'] = $this->model->getMenu(); $result = []; // 第一步:先初始化所有一级菜单,并为每个一级菜单创建空的children数组 foreach ($this->data['menu'] as $item) { if ($item['id_parent'] == 0) { $result[$item['id']] = $item; $result[$item['id']]['children'] = []; } } // 第二步:将二级菜单挂载到对应的一级菜单下 foreach ($this->data['menu'] as $item) { $parentId = $item['id_parent']; // 只处理属于一级菜单的子节点(也就是二级菜单) if ($parentId != 0 && isset($result[$parentId])) { $result[$parentId]['children'][] = $item; } } // 将处理好的菜单赋值给视图数据 $this->data['nav_menu'] = $result; }
这样修改后,即使数据库里存在三级及以上菜单(不过我们已经在SQL里过滤掉了),代码也不会出现警告,逻辑更严谨。
最终效果
优化后的代码不仅能准确生成前两级菜单,还减少了数据库查询的数据量,同时避免了潜在的错误警告,运行更高效、更稳定。
内容的提问来源于stack exchange,提问作者KvinT




