PHP使用mysqli预准备语句出现参数数量不匹配报错如何解决
报错原因及修复方案
第一个报错:bind_param参数数量不匹配
- 根本原因:使用mysqli预准备语句时,没有用
?作为参数占位符,而是直接把用户输入的$name拼接到了SQL字符串中,此时预准备语句识别不到任何待绑定的参数,调用bind_param('s', $name)时传递的1个参数和语句中0个参数不匹配,触发警告。 - 额外问题:直接拼接用户输入的SQL存在严重SQL注入风险,完全不符合预准备语句的使用规范。
第二个报错:array_push第一个参数为null
- 根本原因:第一个报错导致后续SQL执行流程异常,
$stmt->execute()执行失败后,$stmt->get_result()返回非结果集的非法值,后续结果集遍历操作异常;同时代码中两次遍历同一个结果集,第一次遍历已经把结果集指针移动到末尾,第二次遍历拿不到有效行,异常流程下触发数组操作警告。
修复步骤
- 修改预准备SQL,把拼接变量的位置替换为
?占位符 - 移除重复的结果集遍历逻辑,只需要遍历一次结果集即可
- 增加
$_POST参数存在性判断,避免未传name参数时触发额外警告
修复后的完整代码
<?php mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); $servername = "localhost"; $username = "username"; $password = "pass"; $dbname = "databasename"; // 增加参数存在性判断,避免非法请求报错 if (!isset($_POST["name"])) { echo json_encode([]); exit; } $name = $_POST["name"]; $result_array = array(); // 创建连接 $conn = new mysqli($servername, $username, $password, $dbname); // 修复:用?作为参数占位符,不要直接拼接变量 $stmt = $conn->prepare("SELECT name FROM users WHERE name = ?"); $stmt->bind_param("s", $name); $stmt->execute(); $result = $stmt->get_result(); // 移除重复遍历逻辑,仅遍历一次 while ($row = $result->fetch_assoc()) { array_push($result_array, $row); // 注意:如果需要返回纯JSON,不要在这里输出内容,否则会破坏JSON格式 // echo $row['name']; } echo json_encode($result_array); $stmt->close(); $conn->close(); ?>
额外优化建议
如果仅需要判断姓名是否存在,不需要返回完整匹配行,可以将SQL修改为SELECT 1 FROM users WHERE name = ? LIMIT 1,查询效率更高。
内容的提问来源于stack exchange,提问作者wiz 2021
相关产品推荐
相关产品推荐

