Laravel Eloquent创建方法导致完整性约束违规

时间:2016-05-09 10:58:45

标签: php mysql laravel eloquent

我已经建立了以下雄辩的模型和关系:

申请人

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

应用

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

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

他们的迁移:

applicants

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

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');
    });
}

我只想创建一个新申请人,然后为刚创建的申请人添加一个新申请:

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

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

但是,运行此代码时,我收到以下错误:

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
))

据我所知,错误正在发生,因为我传递了一个在数据库中不存在的外键。所以我想知道我在创建申请人的第一次调用数据库时发生了什么:

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

在创建应用程序的第二个语句之前,它是否未写入数据库:

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

...从而导致完整性约束违规?因为如果我dd($applicant)创建它后立即dd(Applicant::find($applicant->id))我会得到记录,我也可以在数据库中查看它。

我发现在我调用create()添加新记录然后逐行构建新应用程序并使用save()重新分解代码之前,我没有&遇到这个问题。所以我很想知道这两个电话是如何不同的(如果他们这样做的话)以及接近这种情况的正确方法是什么,因为我认为这是一个非常简单的事情,我曾多次做过很多次。任何建议都将非常感谢,谢谢!

修改1

更正了对关系的调用:

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

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

修改2

运行此代码:

$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');

并收到相同的错误(更新了页面上的所有错误):

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)

编辑3 添加了相关的迁移

更新1

真奇怪!在我开始重新分解代码之前,我已经通过git恢复到项目的旧版本,但现在因为同样的原因而无法工作!不知道这里发生了什么!?

更新2

刚刚注意到迁移中存在一些非常愚蠢的东西:

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');
    });
}

外键应该是:

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

这里有两点:

  1. 为什么这不会影响我的代码呢?它一直很好,直到现在很奇怪......

  2. 要更新外键约束并试用它以查看它是否正常工作

3 个答案:

答案 0 :(得分:0)

试试这个:

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

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

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

答案 1 :(得分:0)

昨天使用create方法时遇到了完全相同的问题。尝试从1表单保存到两个模型并收到相同的完整性约束错误。

如果您正在使用create,则可以先实例化您的申请人:

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

答案 2 :(得分:0)

在迁移过程中,外键约束引用了错误的外表(它实际上是引用自身),这是一个愚蠢的错误!

create_applications_table迁移的错误代码:

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

正确的代码:

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

现在效果很好:

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

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