You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多级菜单仅统计前两级:基于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

火山引擎 最新活动