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

Laravel 10一对一关联报错:外键约束违反问题排查

Laravel一对一关联模型报错:外键约束失败

Illuminate\Database\QueryException: SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (belajar_laravel_eloquent.wallets, CONSTRAINT wallets_customer_id_foreign FOREIGN KEY (customer_id) REFERENCES customers (id)) (Connection: mysql, SQL: insert into wallets (amount, customer_id) values (5700000, 0))

我是Laravel新手,尝试创建一对一关联模型,但测试时触发上述错误,请问问题出在哪里?


表结构

Schema::create('customers', function (Blueprint $table) {
    $table->string('id', 100)->primary();
    $table->string('name', 100);
    $table->string('email', 100)->unique('customer_email');
});

Schema::create('wallets', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('customer_id', 100);
    $table->bigInteger('amount')->default(0);
    $table->foreign('customer_id')->on('customers')->references('id');
});

Customer模型代码

class Customer extends Model
{
    public $timestamps = false;
    public function wallet(): HasOne
    {
        return $this->hasOne(Wallet::class, 'customer_id', 'id');
    }   
}

Wallet模型代码

class Wallet extends Model
{
    public $timestamps = false;

    public function customer(): BelongsTo
    {
        return $this->BelongsTo(Customer::class, 'customer_id', 'id');
    }
}

测试代码

public function testOneToOneQueryRelation()
{
    $customer = new Customer();
    $customer->id = 'Rinam';
    $customer->name = 'Rinam';
    $customer->email = 'RinamSayang@gmail.com';
    $customer->save();

    $wallet = new Wallet();
    $wallet->amount = 5700000;

    $customer->wallet()->save($wallet);
    self::assertNotNull($wallet->customer_id);
}

问题原因与解决方法

  • 核心原因:Laravel默认模型主键为自增整数类型,但你的Customer模型使用了自定义字符串主键id,框架未正确识别该主键类型,导致关联保存时将customer_id默认设为0,而0不存在于customers表主键中,触发外键约束错误。
  • 解决步骤:
    1. 在Customer模型中明确声明主键属性:
      class Customer extends Model
      {
          public $timestamps = false;
          // 声明主键非自增
          public $incrementing = false;
          // 声明主键类型为字符串
          protected $keyType = 'string';
      
          public function wallet(): HasOne
          {
              return $this->hasOne(Wallet::class, 'customer_id', 'id');
          }   
      }
      
    2. 重新运行测试,此时$customer->wallet()->save($wallet)会正确将customer_id设为Rinam,外键约束验证通过。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 12:41:16