【Laravel】外部キー設定時のエラー:General error: 1824

もくじ

エラー

public function up()
{
  Schema::create('tasks', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->bigInteger('user_id');
    $table->string('content');
    $table->timestamps();

    // 外部キーを設定する
    $table->foreign('user_id')->references('id')->on('users');
  });
}
$ php artisan migrate:refresh
〜〜(略)〜〜
SQLSTATE[HY000]: General error: 1824 Failed to open the referenced table 'テーブル名'

原因

外部キーを設定しているidの型が一致していないことでエラーが起きるようです。

修正

public function up()
{
  Schema::create('tasks', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('user_id');  // 変更
    // $table->bigInteger('user_id')->unsigned(); // こっちでも可
    $table->string('content');
    $table->timestamps();

    // 外部キーを設定する
    $table->foreign('user_id')->references('id')->on('users');
  });
}

上記でも問題ないんですが、ついでに外部キーの設定をもう少し簡潔にしてしまいましょう。

public function up()
{
  Schema::create('tasks', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->unsignedBigInteger('user_id');  // 変更
    // $table->bigInteger('user_id')->unsigned(); // こっちでも可
    $table->string('content');
    $table->timestamps();

    // 外部キーを設定する
    $table->foreignId('user_id')->constrained('users'); // 変更
  });
}

そして、これでもエラーが消えません。。。さらに調べると、コードの問題ではないことが判明しました。

盲点!

ファイル名の日付

ファイル名が親テーブルより子テーブルのほうが日付があとだと、読み込む順番の問題でエラーが発生するようです。

たとえば、tasksテーブルにusersテーブルを外部キーとして設定したい場合のマイグレーションファイル名は以下のようになります。

2020_09_01_120811_create_users_table
2020_09_28_070616_create_tasks_table

マイグレーションファイルを作成するタイミングまでは意識していなかったので盲点でした。

これでマイグレートしたら問題なく動きました。

シーディングの順

日付の名前は親テーブルが先になるようにしなければなりませんが、シーダファイルを作成して実行する時にも注意が必要です。

先ほどの例でいうと、親テーブルのusersテーブルからシーダを実行しなければエラーになります。

$ php artisan db:seed --class=TaksTableSeeder
SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails

このように、子テーブルからシーダを実行してしまうと、外部キーのところで失敗となります。

親テーブルから実行してみるとすんなり成功します。

$ php artisan db:seed --class=UsersTableSeeder
Database seeding completed successfully.
$ php artisan db:seed --class=TasksTableSeeder
Database seeding completed successfully.

作った順にシーダを実行してしまいがちですが、順番にも留意してやっていきましょう!

関連記事

bonoponz.hatenablog.com

参考URL

データベース:マイグレーション 7.x Laravel

PHP - SQLSTATE[HY000]: General error: 1824 で php artisan migrateできない。|teratail

Laravel 外部キー制約エラー General error: 3780 Referencing column - Qiita

laravel - General error: 1824 Failed to open the referenced table - Stack Overflow