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

MySQLi预处理语句重复键错误无法捕获,需自定义提示

MySQLi预处理语句更新用户时捕获唯一约束冲突错误方案

问题背景

使用MySQLi预处理语句执行用户信息更新操作,username字段设置唯一约束。输入重复用户名时,无法触发代码else分支的自定义错误提示,反而抛出致命错误:Uncaught mysqli_sql_exception: Duplicate entry 'admin' for key 'username_2'。此前非预处理语句可正常触发错误提示,尝试通过mysqli_errno == 1062判断无效,仅成功分支能正常跳转。

根因分析

数据库连接代码中开启了严格错误报告模式:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

该模式会将MySQL的所有错误抛出为mysqli_sql_exception异常,而非传统的返回错误码。因此执行$stmt->execute()遇到唯一约束冲突时,不会进入else分支,而是直接抛出异常中断代码执行,这是与非预处理语句(未开启严格模式时)的核心差异。

解决方案

通过异常捕获机制处理约束冲突错误,同时加入事务保证多操作的原子性,修改后的代码如下:

更新操作代码

<?php
session_start();
include("../../functions/connectDatabase.php"); 

if(isset($_POST['updateadviserdata']))
{
    // 开启事务,保证两个操作原子性
    $mysqli->begin_transaction();

    try {
        // 预处理语句无需手动转义,参数绑定自动处理SQL注入
        $id = $_POST['update_id'];
        $fn = $_POST['fname'];
        $mn = $_POST['mname'];
        $ln = $_POST['lname'];
        $un = $_POST['username'];

        // 执行用户信息更新
        $stmt = $mysqli->prepare("UPDATE users SET `firstname`= ?,`middlename`= ?, `lastname`= ?, `username` = ? WHERE `user_id` =?");
        $stmt->bind_param("ssssi", $fn, $mn, $ln, $un, $id );
        $stmt->execute();
        $stmt->close();

        // 插入操作日志
        $stmtUA = $mysqli->prepare("INSERT into history (activity,user_id,date_added) VALUES ('update name',?,NOW() )");
        $stmtUA->bind_param("i", $id);
        $stmtUA->execute();
        $stmtUA->close();

        // 提交事务
        $mysqli->commit();
        $_SESSION['success']= "用户名修改成功"; 
        header('Location: ../../adviseraccount.php');
        exit;
    } catch(mysqli_sql_exception $e) {
        // 回滚事务,避免部分操作生效
        $mysqli->rollback();
        
        // 判断是否为唯一约束冲突(错误码1062)
        if($e->getCode() == 1062) {
            $_SESSION['error'] ="用户名已存在";
        } else {
            // 其他数据库错误可自定义提示或记录日志
            $_SESSION['error'] = "操作失败:" . $e->getMessage();
        }
        header('Location: ../../adviseraccount.php');
        exit;
    }
}

关键优化点

  1. 事务处理:用begin_transaction()、commit()、rollback()保证UPDATE和INSERT操作要么全部成功,要么全部回滚,避免数据不一致。
  2. 异常捕获:通过try-catch捕获mysqli_sql_exception,在catch块中判断错误码1062,触发自定义提示。
  3. 移除冗余操作:删除real_escape_string调用,预处理语句的参数绑定已自动处理SQL注入,无需手动转义。
  4. 跳转后终止代码:header()后调用exit,防止后续代码继续执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 05:10:55