PHP读取MySQL多行数据仅返回第一条的问题排查求助
问题根源与修复方案
嘿,我一眼就看到问题出在哪了——你在内层循环里覆盖了外层查询的结果集变量!
你看,外层循环用$reponses存储module_cmds的查询结果,但当你执行内层的$reponses = $bdd->query(...)时,原来的$reponses(也就是外层的结果集)被直接替换成了内层module_params的查询结果。这样一来,外层的while ($donnee = $reponses->fetch())在第一次循环后,下一次调用fetch()时,操作的已经是内层的结果集了。而内层结果集遍历完之后就没有数据了,外层循环自然就终止了,所以你只能拿到第一条module_cmds的数据。
接下来给你两种修复思路:
方案1:给内层结果集换个变量名
这是最简单的修复方式,只需要把内层查询的结果集变量改成别的名字,避免和外层的$reponses冲突:
$array = array(); // 外层查询用单独的变量名 $cmdsResult = $bdd->query('SELECT * FROM module_cmds WHERE serverId=' . $donnees['server_id'] . ' ORDER BY module'); while ($donnee = $cmdsResult->fetch()){ $array_param = array(); // 内层用不同的变量,不会覆盖外层结果集 $paramsResult = $bdd->query('SELECT * FROM module_params WHERE idModule=' . $donnee['id']); while ($donne = $paramsResult->fetch()){ $array_param_in = array( 'param' => $donne['paramName'], 'value' => $donne['value'] ); array_push($array_param,$array_param_in); } $array_in = array( 'module' => $donnee['module'], 'hash' => $donnee['hash'], 'params' => $array_param ); array_push($array,$array_in); }
方案2:用JOIN查询优化(更推荐)
嵌套查询不仅容易出变量冲突的问题,还会增加数据库的交互次数(每一条module_cmds数据都要发一次查询)。用LEFT JOIN把两张表关联起来,一次性获取所有数据,效率更高,也能避免变量冲突:
$array = array(); // 用LEFT JOIN关联两张表,一次性拿到所有需要的数据 $allResult = $bdd->query('SELECT mc.*, mp.paramName, mp.value FROM module_cmds mc LEFT JOIN module_params mp ON mc.id = mp.idModule WHERE mc.serverId=' . $donnees['server_id'] . ' ORDER BY mc.module'); // 临时数组用来按module分组存储数据 $tempData = array(); while ($donnee = $allResult->fetch()){ $moduleId = $donnee['id']; // 如果是第一次处理这个module,先初始化基础信息 if (!isset($tempData[$moduleId])) { $tempData[$moduleId] = array( 'module' => $donnee['module'], 'hash' => $donnee['hash'], 'params' => array() ); } // 如果有参数数据,添加到params数组 if (!empty($donnee['paramName'])) { $tempData[$moduleId]['params'][] = array( 'param' => $donnee['paramName'], 'value' => $donnee['value'] ); } } // 把临时数组转成最终需要的格式 $array = array_values($tempData);
额外提醒:防范SQL注入!
你现在直接把$donnees['server_id']拼到SQL语句里,这是非常危险的做法,很容易被SQL注入攻击。建议用PDO的预处理语句来替代:
比如外层查询改成这样:
$stmt = $bdd->prepare('SELECT * FROM module_cmds WHERE serverId = ? ORDER BY module'); $stmt->execute([$donnees['server_id']]); $cmdsResult = $stmt->fetchAll();
预处理语句会自动处理变量的转义,能有效避免SQL注入风险。
内容的提问来源于stack exchange,提问作者J3ff3z
相关产品推荐
相关产品推荐

