如何用嵌套do while循环从数据库获取菜单与子菜单?PHP代码求助
解决嵌套do while循环生成导航栏时仅第一个菜单有子菜单的问题
我看了你的代码,问题很明确:你把子菜单的查询语句放在了导航循环的外面,而且只执行了一次,用的是初始的$pageid=1。当第一个导航项循环完后,$cat_query的结果集指针已经走到末尾了,后面的导航项再去循环子菜单时,就没有数据可以取了,所以后面的菜单都没子内容。
问题根源拆解
- 你在导航循环之前就执行了
$cat_sql查询,只获取了nav_id=1的子菜单数据 - 第一个导航项循环时,已经把
$cat_query的结果集全部遍历完了,后续导航项的子菜单循环自然没有数据 - 每个导航项对应的子菜单应该根据当前导航的
nav_id来动态查询,而不是用固定的初始$pageid
解决方案:将子菜单查询移入导航循环内
把获取子菜单的代码放到导航的循环里面,每次循环到一个导航项,就用当前导航的nav_id作为条件去查询对应的子菜单。这样每个导航项都能拿到自己的子菜单数据。
另外,建议用while循环替代do while(避免空结果集时仍输出空标签),同时可以优化代码结构让逻辑更清晰。
修改后的完整代码
<div class="collapse navbar-collapse" id="navbarSupportedContent"> <ul class="navbar-nav mr-auto"> <!-- FETCHING NAVIGATION LIST ALONG WITH DROPDOWN MENU FROM DATABASE --> <?php //SETTING GET PAGES if (isset($_GET['nav'])) { $pageid = $_GET['nav']; }else { $pageid = 1; } //NAVIGATION TABLE QUERY $nav_sql = "SELECT * FROM navigation"; $nav_query = mysqli_query($connection, $nav_sql); // 循环遍历所有导航项 while ($nav_result = mysqli_fetch_assoc($nav_query)) { ?> <li class="nav-item dropdown"> <a class="nav-link dropdown-toggle" role="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" href="?nav=<?php echo $nav_result['nav_id'] ?>"> <?php echo $nav_result['nav_eng']; ?></a> <ul class="dropdown-menu"> <?php // 每次循环导航项时,根据当前nav_id查询对应的子菜单 $cat_sql = "SELECT * FROM category WHERE nav_id = " . $nav_result['nav_id']; $cat_query = mysqli_query($connection, $cat_sql); // 循环输出子菜单 while ($cat_result = mysqli_fetch_assoc($cat_query)) { ?> <li> <a class="dropdown-item" href="?nav=<?php echo $cat_result['cat_id']; ?>"><?php echo $cat_result['cat_eng'] ?></a> </li> <?php } ?> </ul> </li> <?php } ?> </ul> </div>
额外优化建议
- 防止SQL注入:现在的代码直接把变量拼到SQL里,有注入风险,建议用预处理语句:
// 子菜单查询改成预处理方式 $cat_sql = "SELECT * FROM category WHERE nav_id = ?"; $stmt = mysqli_prepare($connection, $cat_sql); mysqli_stmt_bind_param($stmt, "i", $nav_result['nav_id']); mysqli_stmt_execute($stmt); $cat_query = mysqli_stmt_get_result($stmt);
- 减少数据库查询次数:可以先把所有导航和子菜单数据一次性取出,整理成关联数组后再循环输出,性能更优:
// 先获取所有导航数据 $nav_list = mysqli_fetch_all($nav_query, MYSQLI_ASSOC); // 获取所有子菜单并按nav_id分组 $cat_sql = "SELECT * FROM category"; $cat_query = mysqli_query($connection, $cat_sql); $cat_groups = []; while ($cat = mysqli_fetch_assoc($cat_query)) { $cat_groups[$cat['nav_id']][] = $cat; } // 循环导航并输出子菜单 foreach ($nav_list as $nav) { // 输出导航项代码... // 直接从分组数组中取对应子菜单 $sub_cats = $cat_groups[$nav['nav_id']] ?? []; foreach ($sub_cats as $cat) { // 输出子菜单代码... } }
内容的提问来源于stack exchange,提问作者user12210515
相关产品推荐
相关产品推荐

