You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无法更新数据库值: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);
}

问题分析

这段代码里有几个关键问题导致功能失效:

  1. SQL语法错误
    第一个SELECT语句里SELECT *FROM中间缺少空格,应该写成SELECT * FROM,这会直接导致数据库无法解析这条SQL,后续的逻辑自然无法执行。

  2. 逻辑判断矛盾
    你通过pass_open='$gate'查询记录,然后又判断$gate==$name($name是记录的ID字段)。如果pass_open和ID不是同一个值,这个判断永远为假,更新逻辑根本不会触发。

  3. 重复跳转导致代码不执行
    每次执行UPDATE后立刻调用header('Location: ...'),跳转后脚本没有终止,且第二次UPDATE语句大概率不会执行——因为浏览器已经跳转离开当前页面,后续代码的执行没有意义,还可能引发错误。

  4. JSON格式错误
    在else分支的JSON输出部分,你重复添加了"password":"..."键,生成的JSON会是类似{"ID":"xxx","password":"yyy"}"password":"zzz"}的无效格式,前端根本无法解析。

  5. 严重的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);
}
?>

修复说明

  1. 修复了SELECT语句的空格错误,确保SQL能被正确解析。
  2. 替换extract($_GET)为直接获取参数,避免变量覆盖的安全问题。
  3. 使用**预处理语句(Prepared Statements)**处理所有SQL查询,彻底解决SQL注入风险。
  4. 合并了两次UPDATE操作,减少数据库交互次数,同时避免跳转导致的代码不执行问题。
  5. 在header跳转后添加exit,确保脚本终止,防止不必要的代码执行。
  6. 修复了JSON生成逻辑,使用json_encode生成标准的JSON格式,避免手动拼接的语法错误。
  7. 增加了记录不存在、状态不符合条件的提示,方便调试。

内容的提问来源于stack exchange,提问作者87653669

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 07:30:51