简体   繁体   English

Laravel雄辩的创建方法导致违反完整性约束

[英]Laravel Eloquent create method causing integrity constraint violation

I've got the following eloquent models and relations set up: 我已经建立了以下雄辩的模型和关系:

Applicant 申请人

class Applicant {
    public function application()
    {
        return $this->hasOne(Application::class);
    }
}

Application 应用

class Application {
    public function applicant()
    {
        return $this->belongsTo(Applicant::class);
    }

    protected $fillable = [
        // ... other fields
        'applicant_id',
    ];
}

And their migrations: 及其迁移:

applicants table applicants

public function up()
{
    Schema::create('applicants', function (Blueprint $table) {
        $table->increments('id');
        // other fields ...    
    });
}

applications table applications

public function up()
{
    Schema::create('applications', function (Blueprint $table) {
        $table->increments('id');
        // other fields ...
        $table->integer('applicant_id')->unsigned();

        // other relations ...
        $table->foreign('applicant_id')->references('id')->on('applications')->onDelete('cascade');
    });
}

I simply want to create a new applicant then add a new application for the applicant just created: 我只想创建一个新申请人,然后为刚刚创建的申请人添加一个新申请:

$applicant = Applicant::create([
    // data
]);

$application = $applicant->applications()->create([
    // data
]);

However, when running this code I receive the following error: 但是,运行此代码时,出现以下错误:

SQLSTATE[23000]: Integrity constraint violation: 
1452 Cannot add or update a child row: a foreign key constraint fails (
    `dbname`.`applications`, CONSTRAINT `applications_applicant_id_foreign` 
    FOREIGN KEY (`applicant_id`) REFERENCES `applications` (`id`) ON DELETE CASCADE
)
(SQL: insert into `applications` (
    `status`,
    `reference_number`,
    `organisation_id`,
    `qualification_id`,
    `applicant_id`,
    `updated_at`,
    `created_at`
) values (
    pending,
    573066CE59BFE,
    24,
    1,
    12, // <------ applicant_id, i.e. the foreign key!
    2016-05-09 11:30:38,
    2016-05-09 11:30:38
))

As I understand, the error is occuring because I'm passing it a foreign key that doesn't exist in the database. 据我了解,发生此错误是因为我正在向它传递数据库中不存在的外键。 So I was wondering what is happening here with the first call to the DB that I make to create the applicant: 因此,我想知道在第一次致电创建申请人的数据库时会发生什么情况:

$applicant = Applicant::create([
    // data
]);

Is it not written to the DB before the second statement that creates the application: 是否在创建应用程序的第二条语句之前未将其写入数据库:

$application = $applicant->application()->create([
    // data
]);

... and thus causing the integrity constraint violation? ...并因此导致违反完整性约束? Because if I dd($applicant) immediately after creating it or dd(Applicant::find($applicant->id)) I get the record and I can also view it in the DB. 因为如果我在创建dd($applicant)dd(Applicant::find($applicant->id))得到记录,那么我也可以在数据库中查看它。

I've found that prior to re-factoring my code when I was calling create() to add a new record then building up a new application line by line and using save() , I didn't encounter this issue. 我发现在重构代码时,当我调用create()以添加新记录,然后逐行并使用save()建立新的应用程序时,我没有遇到此问题。 So I'm curious to know how both calls differ (if they do) and what would be the correct way to approach such a scenario as I thought it was something very simple with eloquent which I've done many times before. 因此,我很想知道这两个调用之间有什么不同(如果有的话),以及处理这种情况的正确方法是什么,因为我认为这是我以前做过很多次的口才,非常简单。 Any advice would be most appreciated, thanks! 任何建议将不胜感激,谢谢!

Edit 1 编辑1

Corrected call to relation: 更正了联系关系:

$applicant->application()->create(...)

not: 不:

$applicant->applications()->create(...)

Edit 2 编辑2

Running this code: 运行此代码:

$applicant = Applicant::create($this->applicantDataFromRequest($request));

$application = new Application([
    'status'           => 'pending',
    'reference_number' => $request->get('passport_number'),
    'organisation_id'  => $request->get('organisation'),
    'qualification_id' => $request->get('qualification') ?: null,
]);

$applicant->application()->save($application);

dd('done');

And receiving the same error (updated with all errors on page): 并收到相同的错误(已更新为页面上的所有错误):

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`dbname`.`applications`, CONSTRAINT `applications_applicant_id_foreign` FOREIGN KEY (`applicant_id`) REFERENCES `applications` (`id`) ON DELETE CASCADE) (SQL: insert into `applications` (`status`, `reference_number`, `organisation_id`, `qualification_id`, `applicant_id`, `updated_at`, `created_at`) values (pending, 5730970933C7B, 24, 1, 22, 2016-05-09 14:56:25, 2016-05-09 14:56:25))

SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails (`dbname`.`applications`, CONSTRAINT `applications_applicant_id_foreign` FOREIGN KEY (`applicant_id`) REFERENCES `applications` (`id`) ON DELETE CASCADE)

Edit 3 Added relevant migrations 编辑3添加了相关的迁移

Update 1 更新1

Really strange! 真奇怪! I've reverted back to an older version of the project via git where it was working before I began re-factoring my code and now that's not working for the same reason! 在开始重构代码之前,我已经通过git恢复到该项目的较早版本,该版本在该版本中可以正常工作了,而现在由于同样的原因它无法正常工作! No clue what's going on here!? 不知道这是怎么回事!?

Update 2 更新2

Just noticed something really silly in the migrations: 只是注意到迁移过程中确实有些愚蠢:

applications table applications

public function up()
{
    Schema::create('applications', function (Blueprint $table) {
        $table->increments('id');
        // other fields ...
        $table->integer('applicant_id')->unsigned();

        // other relations ...
        $table->foreign('applicant_id')->references('id')->on('applications')->onDelete('cascade');
    });
}

The foreign key should be: 外键应为:

$table->foreign('applicant_id')
    ->references('id')
    ->on('applicants')
    ->onDelete('cascade'); // not applications!

Two points here: 这里有两点:

  1. Why did this not effect my code til now? 为什么这不影响我的代码直到现在? It's been working fine til now weird... 直到现在很奇怪为止,它一直运行良好。

  2. Going to update the foreign key constraint and try it out to see if it works now 要更新外键约束并尝试一下,看看现在是否可以使用

Try this: 尝试这个:

$applicant = new Applicant([
    // data
]);

$application = new Application([
    // data
]);

$applicant->applications()->save($application);

I ran into the exact same issue while using the create method yesterday. 昨天在使用create方法时遇到了完全相同的问题。 Trying to save to two models from 1 form and receiving the same integrity constraint error. 尝试从1种形式保存到两个模型并收到相同的完整性约束错误。

If you're using create, you can instantiate your applicant first: 如果使用create,则可以首先实例化您的申请人:

$applicant = Applicant::create(//applicant data);
$application = new Application(//application data);
$applicant->application()->save($application); 

Within the migrations the foreign key constraint was referencing the wrong foreign table (it was actually referencing itself), a silly mistake! 在迁移过程中,外键约束引用了错误的外表(实际上是在引用自身),这是一个愚蠢的错误!

The erroneous code for the create_applications_table migration: create_applications_table迁移的错误代码:

$table->foreign('applicant_id')
    ->references('id')
    ->on('applications') // wrong table
    ->onDelete('cascade');

The correct code: 正确的代码:

$table->foreign('applicant_id')
    ->references('id')
    ->on('applicants') // correct table
    ->onDelete('cascade');

This now works just fine: 现在可以正常工作:

$applicant = Applicant::create([
    // data
]);

$application = $applicant->applications()->create([
    // data
]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM