无法更新数据库值:PHP代码修改status字段失败求助
PHP更新rent_record表状态失败的问题排查与修复
我写了一段PHP代码,想要把数据库rent_record表中的status字段从pending更新为borrowed,以及从returnP更新为returned,但这段代码没法正常工作。以下是我的代码:
if(isset($_GET['gate'])) { extract($_GET); $timestamp=date("d/m/y h:i:sA",time()); $sql = "SELECT *FROM rent_record WHERE pass_open='$gate'"; $result = $conn->query($sql); $row = mysqli_fetch_array($result); $name = $row["ID"]; $status = $row["status"]; if (($gate==$name) AND ( $status=='pending')) { $sql = "UPDATE rent_record SET status='borrowed' WHERE ID='$name';"; if ($conn->query($sql) === TRUE) header('Location: '.BASE_URL.'/keypad'); else echo "Error: " . $sql . "<br>" . $conn->error; $sql = "UPDATE rent_record SET time_taken='$timestamp' WHERE ID='$name';"; if ($conn->query($sql) === TRUE) header('Location: '.BASE_URL.'/keypad'); else echo "Error: " . $sql . "<br>" . $conn->error; } else if (($gate==$name) AND ( $status=='returnP')) { $sql = "UPDATE rent_record SET status='returned' WHERE ID='$name';"; if ($conn->query($sql) === TRUE) header('Location: '.BASE_URL.'/keypad'); else echo "Error: " . $sql . "<br>" . $conn->error; $sql = "UPDATE rent_record SET time_return='$timestamp' WHERE ID='$name';"; if ($conn->query($sql) === TRUE) header('Location: '.BASE_URL.'/keypad'); else echo "Error: " . $sql . "<br>" . $conn->error; } } else { header("Access-Control-Allow-Origin: *"); header("Content-Type: application/json; charset=UTF-8"); $sql = "SELECT pass_open, pass_closed FROM rent_record WHERE status='pending' OR status='returnP'"; $result = $conn->query($sql); $outp = '['; while($rs = $result->fetch_array(MYSQLI_ASSOC)) { if ($outp != '[') {$outp .= ',';} $outp .= '{"ID":"' . $rs['ID'] . '",'; $outp .= '"password":"' . $rs['pass_open'] . '"}'; $outp .= '"password":"' . $rs['pass_closed'] . '"}'; } $outp .=']'; echo($outp); }
问题分析
这段代码里有几个关键问题导致功能失效:
SQL语法错误
第一个SELECT语句里SELECT *FROM中间缺少空格,应该写成SELECT * FROM,这会直接导致数据库无法解析这条SQL,后续的逻辑自然无法执行。逻辑判断矛盾
你通过pass_open='$gate'查询记录,然后又判断$gate==$name($name是记录的ID字段)。如果pass_open和ID不是同一个值,这个判断永远为假,更新逻辑根本不会触发。重复跳转导致代码不执行
每次执行UPDATE后立刻调用header('Location: ...'),跳转后脚本没有终止,且第二次UPDATE语句大概率不会执行——因为浏览器已经跳转离开当前页面,后续代码的执行没有意义,还可能引发错误。JSON格式错误
在else分支的JSON输出部分,你重复添加了"password":"..."键,生成的JSON会是类似{"ID":"xxx","password":"yyy"}"password":"zzz"}的无效格式,前端根本无法解析。严重的SQL注入风险
使用extract($_GET)和直接把用户输入拼进SQL语句,这会让你的代码轻易被SQL注入攻击,可能导致数据泄露或被篡改。
修复后的代码
我把这些问题都修复了,同时优化了代码结构:
<?php if(isset($_GET['gate'])) { // 避免使用extract,直接获取参数,防止变量覆盖风险 $gate = $_GET['gate']; $timestamp = date("d/m/y h:i:sA", time()); // 修复SELECT语句的空格问题,同时使用预处理语句防止SQL注入 $sql = "SELECT ID, status FROM rent_record WHERE pass_open = ?"; $stmt = $conn->prepare($sql); $stmt->bind_param("s", $gate); // 绑定字符串类型参数 $stmt->execute(); $result = $stmt->get_result(); // 检查是否查询到记录 if($row = $result->fetch_assoc()) { $recordId = $row["ID"]; $currentStatus = $row["status"]; // 根据当前状态执行对应的更新操作 if($currentStatus === 'pending') { // 合并两个UPDATE为一条语句,减少数据库请求 $updateSql = "UPDATE rent_record SET status='borrowed', time_taken=? WHERE ID=?"; $updateStmt = $conn->prepare($updateSql); $updateStmt->bind_param("ss", $timestamp, $recordId); if($updateStmt->execute()) { header('Location: '.BASE_URL.'/keypad'); exit; // 跳转后必须终止脚本,防止后续代码执行 } else { echo "更新失败: " . $updateStmt->error; } } elseif($currentStatus === 'returnP') { $updateSql = "UPDATE rent_record SET status='returned', time_return=? WHERE ID=?"; $updateStmt = $conn->prepare($updateSql); $updateStmt->bind_param("ss", $timestamp, $recordId); if($updateStmt->execute()) { header('Location: '.BASE_URL.'/keypad'); exit; } else { echo "更新失败: " . $updateStmt->error; } } else { echo "当前记录状态不符合更新条件: " . htmlspecialchars($currentStatus); } } else { echo "未找到匹配pass_open的记录: " . htmlspecialchars($gate); } } else { header("Access-Control-Allow-Origin: *"); header("Content-Type: application/json; charset=UTF-8"); $sql = "SELECT ID, pass_open, pass_closed FROM rent_record WHERE status='pending' OR status='returnP'"; $result = $conn->query($sql); // 使用数组存储数据,最后用json_encode生成正确的JSON $response = []; while($rs = $result->fetch_assoc()) { $response[] = [ "ID" => $rs['ID'], "pass_open" => $rs['pass_open'], "pass_closed" => $rs['pass_closed'] ]; } echo json_encode($response); } ?>
修复说明
- 修复了SELECT语句的空格错误,确保SQL能被正确解析。
- 替换
extract($_GET)为直接获取参数,避免变量覆盖的安全问题。 - 使用**预处理语句(Prepared Statements)**处理所有SQL查询,彻底解决SQL注入风险。
- 合并了两次UPDATE操作,减少数据库交互次数,同时避免跳转导致的代码不执行问题。
- 在
header跳转后添加exit,确保脚本终止,防止不必要的代码执行。 - 修复了JSON生成逻辑,使用
json_encode生成标准的JSON格式,避免手动拼接的语法错误。 - 增加了记录不存在、状态不符合条件的提示,方便调试。
内容的提问来源于stack exchange,提问作者87653669
相关产品推荐
相关产品推荐

