如何基于数据库主/子分类数据实现下拉式导航菜单?
实现数据库驱动的Bootstrap多级下拉菜单
嘿,看你已经在着手做基于数据库的多级下拉菜单了,从代码里的dropdown、dropdown-toggle这些类来看,应该是用了Bootstrap对吧?我来帮你补全代码,解决子分类的渲染问题,顺便优化一下过时的数据库操作逻辑~
先确认下分类表的常见结构(你可以根据自己的表调整)
一般分类表会这么设计:
categories表:id:分类ID(主键)name:分类名称parent_id:父分类ID(主分类的parent_id设为0或者null)
第一步:替换过时的mysql扩展,整理分类数据
划重点:mysql_*系列函数在PHP7之后就被彻底废弃了,再用会报错!强烈建议换成mysqli或者PDO,下面我用mysqli面向过程的写法示例
先把数据库里的分类数据拉出来,整理成「主分类对应子分类数组」的树形结构,这样渲染的时候更方便:
// 数据库连接(换成你自己的数据库配置) $conn = mysqli_connect('localhost', '你的用户名', '你的密码', '你的数据库名'); if (!$conn) { die("数据库连不上:" . mysqli_connect_error()); } // 拉取所有分类,按父分类和ID排序 $sql = "SELECT id, name, parent_id FROM categories ORDER BY parent_id, id"; $result = mysqli_query($conn, $sql); // 把数据整理成树形结构 $categoryTree = []; while ($row = mysqli_fetch_assoc($result)) { if ($row['parent_id'] == 0) { // 主分类,作为数组的键 $categoryTree[$row['id']] = [ 'name' => $row['name'], 'children' => [] ]; } else { // 子分类,挂到对应的主分类下面 if (isset($categoryTree[$row['parent_id']])) { $categoryTree[$row['parent_id']]['children'][] = $row; } } }
第二步:渲染Bootstrap多级下拉菜单
现在用整理好的树形数据,来完善你原来的代码,实现主分类下拉展示子分类的效果:
<li class="dropdown"> <?php foreach ($categoryTree as $mainCategory): ?> <!-- 主分类下拉触发按钮 --> <a href="#" class="dropdown-toggle" data-toggle="dropdown"> <?php echo htmlspecialchars($mainCategory['name']); ?> <b class="caret"></b> </a> <!-- 子分类下拉菜单容器 --> <ul class="dropdown-menu multi-column columns-3"> <div class="row"> <?php foreach ($mainCategory['children'] as $index => $subCategory): ?> <!-- 每3个子分类分一列(对应columns-3) --> <?php if ($index % 3 == 0): ?> <div class="col-sm-4"> <?php endif; ?> <ul class="multi-column-dropdown"> <li> <a href="#"><?php echo htmlspecialchars($subCategory['name']); ?></a> </li> </ul> <?php if (($index + 1) % 3 == 0 || $index == count($mainCategory['children']) - 1): ?> </div> <?php endif; ?> <?php endforeach; ?> </div> </ul> <?php endforeach; ?> </li>
几个重要的小细节
- 安全第一:用
htmlspecialchars()转义分类名称,防止XSS攻击,别小看这个,很重要! - Bootstrap依赖:要确保你已经引入了Bootstrap的CSS和JS,还有jQuery(因为Bootstrap的下拉组件需要jQuery支持)
- 三级分类扩展:如果以后要加三级分类,只需要在树形结构里再嵌套一层,渲染时多写一个foreach循环就行
- 数据库优化:如果分类数据很多,给
parent_id字段加个索引,查询速度会快很多
为啥要换掉mysql扩展?
原来的mysql_fetch_array()这些函数早就被淘汰了,PHP7及以上版本直接用不了,会抛出致命错误,所以一定要换成mysqli或者PDO,上面的示例是mysqli面向过程的写法,你也可以用面向对象的写法或者PDO,看你自己习惯~
内容的提问来源于stack exchange,提问作者Arebhy Sridaran




