
本文详解如何使用 MySQLi 预处理语句(prepared statement)安全执行带参数的 SELECT 查询,并通过 bind_result() 和 fetch() 正确获取并遍历结果,避免因未绑定输出变量导致数据无法读取的问题。
本文详解如何使用 mysqli 预处理语句(prepared statement)安全执行带参数的 select 查询,并通过 `bind_result()` 和 `fetch()` 正确获取并遍历结果,避免因未绑定输出变量导致数据无法读取的问题。
在使用 MySQLi 的预处理语句执行 SELECT 查询后,不能像普通 mysqli_query() 那样直接用 $row['field'] 访问字段——因为 stmt->fetch() 本身不返回关联数组,而是将查询结果按顺序填充到预先绑定的 PHP 变量中。你原始代码中直接使用 $row['pcode'] 等变量,但并未声明或绑定 $row,因此所有字段值均为 null,循环体虽执行,但输出为空,最终 if ($i==0) 被触发,显示“No Results”。
✅ 正确做法是:在 execute() 后调用 bind_result(),显式绑定与查询字段一一对应的 PHP 变量,再用 fetch() 每次提取一行到这些变量中:
$query = "SELECT pcode, price, description FROM products WHERE description LIKE ? ORDER BY price";
$stmt = $mysqli->prepare($query);
$search_criteria = '%' . $search_criteria . '%';
$stmt->bind_param('s', $search_criteria);
$stmt->execute();
// ✅ 关键步骤:绑定结果变量(顺序、类型、数量必须与 SELECT 字段完全一致)
$pcode = $price = $description = null;
$stmt->bind_result($pcode, $price, $description);
$i = 0;
while ($stmt->fetch()) {
$trow = ($i++ % 2 === 0) ? 'even' : 'odd';
echo "<tr class="{$trow}">";
echo "<td>" . htmlspecialchars($pcode) . "</td>";
echo "<td>" . htmlspecialchars($price) . "</td>";
echo "<td>" . htmlspecialchars($description) . "</td>";
echo "</tr>";
}
if ($i === 0) {
echo "<tr class="even"><td colspan="3"><h3>No Results.</h3></td></tr>";
}
$stmt->close();
⚠️ 注意事项:
- bind_result() 的变量顺序必须严格匹配 SELECT 子句中的字段顺序(此处为 pcode, price, description);
- 建议对输出内容使用 htmlspecialchars() 防止 XSS 攻击;
- 原始代码中混用了已废弃的 mysql_* 函数(如 mysql_connect),该扩展自 PHP 7.0 起已被彻底移除,务必统一使用 mysqli 或 PDO;
- 若需更灵活的关联数组访问(如 $row['pcode']),可改用 get_result()->fetch_assoc()(需确保 MySQLi 处于缓冲模式):
$result = $stmt->get_result(); while ($row = $result->fetch_assoc()) { echo "<td>" . htmlspecialchars($row['pcode']) . "</td>"; // ... 其他字段 }
总结:参数化查询的安全优势不可替代,但遍历结果必须配合正确的结果绑定机制。bind_result() + fetch() 是轻量高效的选择;若需动态字段访问,优先选用 get_result() + fetch_assoc() 组合,并确保启用 MYSQLI_STORE_RESULT 模式。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











