PHP
初心者
laravel
laravel5.6

Laravelのマイグレーションで外部制約する時の注意点

Laravelのマイグレーションで外部制約する時の注意点

Laravelのマイグレーションで外部制約つけようとしたら、
えー。。。ってなったので備忘録。

  Schema::create('hoges', function (Blueprint $table) {
    $table->unsignedInteger('user_id');
    $table->foreign('user_id')
      ->references('id')
      ->on('users');
  });

よし、実行だ!

  SQLSTATE[HY000]: General error: 1215 Cannot add foreign key constraint
  (SQL: alter table `hoges` add constraint `hoges_user_id_foreign` foreign key (`user_id`) references `users` (`id`))

えー。。。

原因と対応

その1.参照する側と参照される側のデータの型が違う

大抵の場合、親側はincrements('id')とかだと思います。
この時、子側がinteger('user_id')などとするとエラーになる。

incrementsで生成されるのはINT(10) UNSIGNEDなのです。

なので、子側も、

  unsignedInteger('user_id');

もしくは

  integer('user_id')->unsigned()

とすれば通ります。

その2.参照するテーブルやカラムがまだない

php artisan make:migrationでマイグレーションファイルをポコポコ作成していざ実行。はい、エラー。
今回はこのパターンでした。
ポコポコ作ることに原因があるのではなく、作成順は大丈夫ですか?という話。

  Schema::create('hoges', function (Blueprint $table) {
    $table->unsignedInteger('user_id');
    $table->foreign('user_id')
      ->references('id')
      ->on('users');
  });

先ほどのこの例で言うと、usersテーブルよりもhogesテーブルのマイグレーションが先に実行をされると、
当然ながらusersテーブルはないのでエラーになります。

マイグレーションの実行はプレフィックスの日付が古いものから順に実行されます。
プレフィックスの日付を意識するのは何だかスマートじゃないぞ!
と思い、今回はテーブルの作成とテーブルの紐付けを別にして管理することにしました。

作成するファイルは普通に作成して、

2018_03_26_235054_create_hoges_table
  class CreateHogesTable extends Migration {
    public function up() {
      Schema::create('hoges', function (Blueprint $table) {
        $table->unsignedInteger('user_id');
      });
    }
  }

紐付けするファイルは作成後に、必ず最後に実行されるようにリネーム。

9999_03_26_235054_relate_tables.php
  class RelateTables extends Migration {
    public function up() {
      Schema::table('hoges', function (Blueprint $table) {
        $table->foreign('user_id')
          ->references('id')
          ->on('users');
      });
    }
  }

おしまい。結局プレフィックス頼みですね。。。
(より良い方法がありましたらご教授願います。)