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
相关产品推荐
相关产品推荐

