
本文详解如何修复旅行预订系统中因未正确处理mysql查询结果而导致的误报“目的地不可用”问题,涵盖结果集提取、sql注入防护及前端响应完整性优化。
本文详解如何修复旅行预订系统中因未正确处理mysql查询结果而导致的误报“目的地不可用”问题,涵盖结果集提取、sql注入防护及前端响应完整性优化。
在您提供的PHP脚本中,核心逻辑缺陷在于:mysqli_query() 返回的是一个 结果集对象(mysqli_result),而非可用的数值;而您却直接用 $res > 0 和 $res < 1 进行比较——这始终为 true(因对象在布尔上下文中恒为 true),导致无论库存是否充足,均错误触发不可用提示。
✅ 正确做法:获取并验证实际库存值
必须先执行查询,再显式提取数据(如 fetch_assoc()),才能获得 n_package 的真实数值:
// ✅ 使用预处理语句防止SQL注入(强烈推荐)
$request1 = "SELECT n_package FROM destination WHERE country = ?";
$stmt = $connection->prepare($request1);
$stmt->bind_param("s", $location);
$stmt->execute();
$result = $stmt->get_result();
if ($result->num_rows === 0) {
// 该国家不存在于destination表中
echo '<script>alert("' . $msg3 . '");</script>';
} else {
$row = $result->fetch_assoc();
$available = (int)$row['n_package'];
if ($available <= 0) {
echo '<script>alert("' . $msg3 . '");</script>';
} else {
// ✅ 库存充足:执行扣减
$update = "UPDATE destination SET n_package = n_package - 1 WHERE country = ?";
$stmt2 = $connection->prepare($update);
$stmt2->bind_param("s", $location);
$stmt2->execute();
echo '<script>alert("' . $msg2 . '");</script>';
}
}⚠️ 关键注意事项
- 绝不拼接用户输入到SQL中:原始代码中 $location 直接嵌入查询字符串,极易遭受SQL注入攻击(例如输入 'Italy'; DROP TABLE destination; --)。预处理语句(prepare + bind_param)是标准防御方案。
- 空字段校验应独立于数据库操作:建议在查询前完成全部表单验证,避免无效请求触达数据库。
- JavaScript弹窗不能替代完整页面响应:仅输出 <script>alert(...)</script> 会导致浏览器收到不完整HTML(无DOCTYPE、html、body等),可能引发渲染异常或安全策略拦截。生产环境应配合重定向(如 header('Location: success.php'))或返回结构化JSON供AJAX处理。
- 添加错误处理:对 mysqli_connect()、prepare()、execute() 等关键操作添加 if (!$stmt) 判断,并启用 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT) 全局捕获异常。
✅ 完整逻辑流程总结
- 接收POST数据 → 2. 校验必填字段 → 3. 预处理查询目标国家库存 → 4. 提取n_package值 → 5. 判断是否≥1 → 6. 是则扣减并提示成功;否则提示不可用。
遵循以上改进,即可彻底解决“有库存却提示不可用”的问题,同时大幅提升代码安全性与健壮性。



















