You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP分类与子分类下拉菜单问题:子分类无法关联对应主分类

问题分析与修复方案

嘿,我一眼就揪出问题啦——你当前的getsubcat()方法不管主分类是谁,都硬取了categories表中第一个分类的ID去查询子分类,这就导致所有主分类都显示同一组子分类!咱们一步步来修复这个问题:

第一步:修复Model的子分类查询方法

把getsubcat()改成接收主分类ID作为参数,这样就能针对每个主分类查询对应的子分类:

class Post{
    private $db;
    public function __construct(){
        $this->db = new Database;
    }
    public function getcat(){
        $this->db->query('SELECT * FROM categories'); // 注意你原来的表名写错了:categoires → categories
        $results = $this->db->resultSet();
        return $results;
    }
    // 修改这里:接收$cat_id参数
    public function getsubcat($cat_id){
        $this->db->query('SELECT * FROM sub_cat WHERE cat_id =:cat_id');
        $this->db->bind(':cat_id', $cat_id);
        $results = $this->db->resultSet();
        return $results;
    }
}

(顺带提一句:你原来的getcat()里表名写成了categoires,少了个r,记得改成categories哦)

第二步:修改Controller,关联主分类与子分类

在Controller里循环每个主分类,为其绑定对应的子分类,把数据整理成“主分类包含子分类”的结构:

public function index(){
    $cats = $this->postModel->getcat();
    // 给每个主分类挂载它自己的子分类
    foreach($cats as $cat){
        $cat->sub_cats = $this->postModel->getsubcat($cat->id);
    }
    $data = [
        'cats'=> $cats
    ];
    $this->view('posts/index', $data);
}

第三步:更新View,正确渲染对应子分类

现在View可以直接循环每个主分类下的子分类了,还可以加个判断避免空列表:

<?php foreach($data['cats'] as $cat) : ?>
<li>
    <?php echo $cat->cat_name; ?>
    <?php if(!empty($cat->sub_cats)) : ?>
        <ul>
            <?php foreach($cat->sub_cats as $sub_cat) : ?>
                <li><?php echo $sub_cat->sub_name; ?></li>
            <?php endforeach; ?>
        </ul>
    <?php endif; ?>
</li>
<?php endforeach; ?>

进阶优化:减少数据库查询次数(解决N+1问题)

上面的方案会对每个主分类发起一次查询,当主分类很多时效率不高。可以在Model里用LEFT JOIN一次性查询所有主分类和子分类,再整理成分组结构:

public function getCategoriesWithSubcats(){
    $this->db->query('
        SELECT c.id AS cat_id, c.cat_name, sc.id AS sub_id, sc.sub_name
        FROM categories c
        LEFT JOIN sub_cat sc ON c.id = sc.cat_id
        ORDER BY c.cat_name, sc.sub_name
    ');
    $results = $this->db->resultSet();
    
    // 把查询结果整理成主分类分组的格式
    $categories = [];
    foreach($results as $row){
        if(!isset($categories[$row->cat_id])){
            $categories[$row->cat_id] = (object)[
                'id' => $row->cat_id,
                'cat_name' => $row->cat_name,
                'sub_cats' => []
            ];
        }
        // 只有存在子分类时才添加
        if($row->sub_id){
            $categories[$row->cat_id]->sub_cats[] = (object)[
                'id' => $row->sub_id,
                'sub_name' => $row->sub_name
            ];
        }
    }
    return array_values($categories); // 转换成索引数组返回
}

然后Controller只需要调用这个方法即可:

public function index(){
    $cats = $this->postModel->getCategoriesWithSubcats();
    $data = [
        'cats'=> $cats
    ];
    $this->view('posts/index', $data);
}

View的代码和之前一样就能正常工作啦!

内容的提问来源于stack exchange,提问作者Martín

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 03:55:33