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

Laravel自定义忘记密码报错SQLSTATE[23000]:主键重复

解决Laravel自定义忘记密码时的SQL重复主键错误

错误原因

你遇到的SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'example@gmail.com' for key 'PRIMARY'错误,根源是**password_resets表将email字段单独设为了主键**。

Laravel默认的密码重置逻辑中,同一邮箱可多次请求重置链接:每次请求时会先删除该邮箱已有的旧重置记录,再插入新的token。但如果email是唯一主键,当该邮箱已有重置记录时,新的插入操作会触发主键唯一性约束,导致报错。

解决方案

方案1:修正表结构(推荐,符合Laravel默认设计)

移除email的单独主键,改为设置email和token的联合主键,这样同一邮箱可对应多个token(Laravel会自动清理旧记录):

  1. 创建新的迁移文件:
    php artisan make:migration fix_password_resets_table
    
  2. 在生成的迁移文件中编写结构修改逻辑:
    use Illuminate\Database\Migrations\Migration;
    use Illuminate\Database\Schema\Blueprint;
    use Illuminate\Support\Facades\Schema;
    
    return new class extends Migration {
        public function up() {
            Schema::table('password_resets', function (Blueprint $table) {
                // 移除原有的email主键
                $table->dropPrimary('email');
                // 设置email和token为联合主键
                $table->primary(['email', 'token']);
            });
        }
    
        public function down() {
            Schema::table('password_resets', function (Blueprint $table) {
                $table->dropPrimary(['email', 'token']);
                $table->primary('email');
            });
        }
    };
    
  3. 执行迁移生效:
    php artisan migrate
    

方案2:在自定义逻辑中先删除旧记录(不修改表结构时用)

如果不想调整表结构,需确保每次生成新重置token前,先删除该邮箱的旧记录:
在你的ForgotPasswordController的重置链接发送方法中,添加删除逻辑:

use Illuminate\Support\Facades\DB;

// 示例:在处理请求的方法中
public function sendResetLinkEmail(Request $request)
{
    // 验证请求参数...

    // 先删除该邮箱已有的重置记录
    DB::table('password_resets')->where('email', $request->email)->delete();

    // 然后执行生成token、发送邮件的逻辑...
}

额外检查

如果你的自定义控制器重写了Laravel默认的密码重置逻辑,确认是否遗漏了PasswordBroker中默认的deleteExistingTokens方法调用——这个方法负责清理旧记录,是避免重复插入的关键。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 12:02:17