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

PHP注册报错:Duplicate entry for key 'email' 原因及解决咨询

PHP注册系统邮箱重复错误分析与解决

错误含义解释

你遇到的Fatal error: Uncaught mysqli_sql_exception: Duplicate entry...错误,本质是:你的数据库user表的email字段设置了唯一约束(UNIQUE KEY),当尝试插入已存在的邮箱地址时,MySQL会触发1062错误码(重复条目);而PHP 8.0+版本的mysqli默认开启了严格异常模式,执行失败时直接抛出异常,导致原代码里的错误判断逻辑根本没机会执行。

原代码失效原因

原代码里的if ($stmt->execute()) else分支判断$mysqli->errno === 1062之所以没用,是因为mysqli默认抛出异常,当execute()执行失败时直接抛出了mysqli_sql_exception,程序直接终止,不会走到else分支里的错误判断。

正确处理方式

方案1:用try/catch捕获异常(你已采用的方法)

直接捕获执行阶段抛出的异常,通过异常对象获取错误码判断:

<?php
if (empty($_POST["name"])){
    die("请填写姓名");
}

if (! filter_var($_POST["email"], FILTER_VALIDATE_EMAIL)) {
    die("请输入有效的邮箱地址");
}

if (strlen($_POST["password"])<8) {
    die("密码长度至少8位");            
}

if (! preg_match("/[a-z]/i", $_POST["password"])) {
    die("密码必须包含至少一个字母");
}

if (! preg_match("/[0-9]/", $_POST["password"])) {
    die("密码必须包含至少一个数字");
}

if ($_POST["password"] !== $_POST["confirmpassword"]) {
    die("两次输入的密码不一致");
}

$password_hash = password_hash($_POST["password"], PASSWORD_DEFAULT);

$mysqli = require __DIR__ . "/database.php";

$sql = "INSERT INTO user (name, email, password_hash) VALUES (?,?,?)";

$stmt = $mysqli->stmt_init();

if (! $stmt->prepare($sql)){
    die("SQL错误:" . $mysqli->error);
}

$stmt->bind_param("sss", $_POST["name"], $_POST["email"], $password_hash);

try {
    $stmt->execute();
    echo "注册成功";
} catch (mysqli_sql_exception $e) {
    if ($e->getCode() === 1062) {
        die("邮箱已被占用");
    }
    die("注册失败:" . $e->getMessage());
}

方案2:关闭mysqli异常模式,沿用原逻辑

如果你想保留原代码的分支判断结构,可以关闭mysqli的严格异常报告,让它返回错误而非抛出异常:

<?php
// 先关闭严格异常模式
mysqli_report(MYSQLI_REPORT_OFF);

// 以下表单验证逻辑不变...

$password_hash = password_hash($_POST["password"], PASSWORD_DEFAULT);

$mysqli = require __DIR__ . "/database.php";

$sql = "INSERT INTO user (name, email, password_hash) VALUES (?,?,?)";

$stmt = $mysqli->stmt_init();

if (! $stmt->prepare($sql)){
    die("SQL错误:" . $mysqli->error);
}

$stmt->bind_param("sss", $_POST["name"], $_POST["email"], $password_hash);

if ($stmt->execute()) {
    echo "注册成功";
} else {
    if ($mysqli->errno === 1062) {
        die("邮箱已被占用");
    }
    die("注册失败:" . $mysqli->error . " " . $mysqli->errno);
}

额外优化建议

除了依赖数据库唯一约束,还可以在插入前主动查询邮箱是否存在,提前给用户提示:

// 在插入逻辑前添加查询
$check_sql = "SELECT id FROM user WHERE email = ?";
$check_stmt = $mysqli->prepare($check_sql);
$check_stmt->bind_param("s", $_POST["email"]);
$check_stmt->execute();
// 如果能查询到结果,说明邮箱已存在
if ($check_stmt->fetch()) {
    die("邮箱已被占用");
}

注意:这个查询只能做前置提示,数据库的唯一约束不能去掉——因为存在竞态条件(比如两个请求同时检查同一邮箱,都通过后同时插入),唯一约束是最后一道防线。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.28 10:31:16