PHP while循环内嵌套foreach返回重复行问题排查
嵌套复选框列表重复输出问题排查与修复
我正在尝试用PHP创建一个嵌套复选框列表,编写了while循环内嵌套多层foreach循环的代码。目前输出结果大致符合预期,但存在第一个foreach循环的内容随循环次数增加而重复的问题(比如第一个主复选框显示1次,第二个显示2次,第三个显示3次),请问代码中哪里出现了问题?
<?php $sql_concern="SELECT * FROM sister_concern where Base_user='$User_id' And Status='Active'"; $result_concern = mysqli_query($link,$sql_concern); if(mysqli_num_rows($result_concern) > 0){ echo '<ul>'; while($row = mysqli_fetch_array($result_concern)){ $sisid=$row['Id']; $name=$row['Name']; $namearray[]=$name; foreach($namearray as $data){ echo '<li style="list-style-type:none;"><input type="checkbox" name="sister_concern" class="chkMainConcern" id="chkMainConcern'.$sisid.'" value="'.$sisid.'" > '.$name.' </li>'; //fetch module Name for each concern $sql_module="SELECT * FROM Module where Status='Active'"; $result_module = mysqli_query($link,$sql_module); //this one coming duplicate echo '<ul class="modulename'.$sisid.'" style="display:none;">'; while($rowmodule = mysqli_fetch_array($result_module)){ $modid=$rowmodule['Id']; $modname=$rowmodule['Name']; $modearray[]=$modname; foreach($modearray as $val){ //module name echo '<li style="list-style-type:none;"><input type="checkbox" value="'.$modid.'"> '.$rowmodule['Name'].' </li>'; //fetch module permission for each module $sql_modhooks="SELECT * FROM Module_hooks where Status='Active' and ModuleID='$modid'"; $result_modhooks = mysqli_query($link,$sql_modhooks); echo '<ul class="modulehooks'.$modid.'" style="display:none;">'; while($row_modhooks = mysqli_fetch_array($result_modhooks)){ echo '<li style="list-style-type:none;"><input type="checkbox" value="'.$modid.'"> '.$row_modhooks['display_txt'].' </li>'; } echo '</ul>'; } } echo '</ul>'; } } echo '</ul>'; }else{ echo 'No Concern Added Yet! Pls Add a Concer First'; } ?>
问题根源
- 数组未重置导致重复遍历:在遍历
sister_concern的while循环中,$namearray[]=$name;会不断将当前项追加到数组中,后续的foreach($namearray as $data)会遍历整个数组,导致第N次循环时输出N次主复选框(包含之前所有的sister concern)。同理,$modearray[]=$modname;也会导致模块被重复输出。 - 多余的foreach循环:代码中完全不需要用数组存储名称再遍历,直接输出当前循环的
$name和$rowmodule['Name']即可,foreach属于冗余逻辑。
修复后的代码
<?php $sql_concern = "SELECT * FROM sister_concern WHERE Base_user='$User_id' AND Status='Active'"; $result_concern = mysqli_query($link, $sql_concern); if (mysqli_num_rows($result_concern) > 0) { echo '<ul>'; while ($row = mysqli_fetch_array($result_concern)) { $sisid = $row['Id']; $name = $row['Name']; // 直接输出当前sister concern的复选框 echo '<li style="list-style-type:none;"><input type="checkbox" name="sister_concern" class="chkMainConcern" id="chkMainConcern' . $sisid . '" value="' . $sisid . '" > ' . $name . ' </li>'; // 获取当前concern对应的模块 $sql_module = "SELECT * FROM Module WHERE Status='Active'"; $result_module = mysqli_query($link, $sql_module); echo '<ul class="modulename' . $sisid . '" style="display:none;">'; while ($rowmodule = mysqli_fetch_array($result_module)) { $modid = $rowmodule['Id']; $modname = $rowmodule['Name']; // 直接输出当前模块的复选框 echo '<li style="list-style-type:none;"><input type="checkbox" value="' . $modid . '"> ' . $modname . ' </li>'; // 获取当前模块的权限 $sql_modhooks = "SELECT * FROM Module_hooks WHERE Status='Active' AND ModuleID='$modid'"; $result_modhooks = mysqli_query($link, $sql_modhooks); echo '<ul class="modulehooks' . $modid . '" style="display:none;">'; while ($row_modhooks = mysqli_fetch_array($result_modhooks)) { echo '<li style="list-style-type:none;"><input type="checkbox" value="' . $modid . '"> ' . $row_modhooks['display_txt'] . ' </li>'; } echo '</ul>'; } echo '</ul>'; } echo '</ul>'; } else { echo 'No Concern Added Yet! Pls Add a Concern First'; } ?>
额外优化建议
- SQL注入风险:当前代码直接将变量拼接到SQL语句中,存在注入风险,建议使用
mysqli_prepare预处理语句替代。 - 代码冗余优化:可将模块、权限查询封装为独立函数,提升代码复用性与可读性。
- 样式分离:将内联样式转移到外部CSS文件,便于统一维护。
内容的提问来源于stack exchange,提问作者Mithu
相关产品推荐
相关产品推荐

