🔖

Laravel8で外部キー制約を追加する

2021/11/05に公開

概要

Laravel8 で外部キーを作成するときに、手順に注意しないとと敗するので、まとめます。

作成手順

主に2つに注意しました。

手順 1 外部キーの型をそろえる

失敗例

たとえば、以下のように作成してしまうとうまくいきません。
なぜなら、子テーブルの外部キーと親テーブルの参照先のキーの型が異なるからです。

子テーブル。

public function up()
{
    Schema::create('artists', function (Blueprint $table) {
        $table->id();
        $table->string('name')->unique();
        $table->int('country_id'); # 外部キー
        $table->foreign('country_id')->references('id')->on('countries'); # 外部キー制約をつける
        $table->timestamps();
    });
}

親テーブル。

public function up()
{
    Schema::create('countries', function (Blueprint $table) {
        $table->id(); # 参照先
        $table->string('name')->unique();
        $table->timestamps();
    });
}

成功例

そのため、適切な型で指定することによって解決できます。

解決例1。

$table->unsignedBigInteger('country_id'); # 外部キー
$table->foreign('country_id')->references('id')->on('countries'); # 外部キー制約をつける

しかし、以下の書き方のほうが一行で型を気にせずかけるのでお勧めします。

解決例2。

$table->foreignId('country_id')->constrained('countries');

ですので、子テーブルは以下になります。親テーブルは変更ありません。

子テーブル。

public function up()
{
    Schema::create('artists', function (Blueprint $table) {
        $table->id();
        $table->string('name')->unique();
        $table->foreignId('country_id')->constrained('countries'); // 外部キー制約と型の制約を一度につける
        $table->timestamps();
    });
}

親テーブル。

public function up()
{
    Schema::create('countries', function (Blueprint $table) {
        $table->id(); // 参照先
        $table->string('name')->unique();
        $table->timestamps();
    });
}

手順 2 migration の順番を親テーブル->子テーブルにする

Laravel の migration コマンド(php artisan migrate)はファイル名の日付の順番で実行します。
そのときに、子テーブルが親テーブルよりも先に作成されてしまうと失敗します。
ですので、ファイル名が親テーブル->子テーブルの順番になるように名前を変更します。

失敗例

2021_10_16_014827_create_child_table.php
2021_11_03_091723_create_parent_table.php # 親の方が後になっていると失敗する

成功例

2021_11_03_091723_create_parent_table.php
2021_11_03_094244_create_child_table.php # 子が後になるように修正する

Discussion