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
テーブルはないのでエラーになります。
マイグレーションの実行はプレフィックスの日付が古いものから順に実行されます。
プレフィックスの日付を意識するのは何だかスマートじゃないぞ!
と思い、今回はテーブルの作成とテーブルの紐付けを別にして管理することにしました。
作成するファイルは普通に作成して、
class CreateHogesTable extends Migration {
public function up() {
Schema::create('hoges', function (Blueprint $table) {
$table->unsignedInteger('user_id');
});
}
}
紐付けするファイルは作成後に、必ず最後に実行されるようにリネーム。
class RelateTables extends Migration {
public function up() {
Schema::table('hoges', function (Blueprint $table) {
$table->foreign('user_id')
->references('id')
->on('users');
});
}
}
おしまい。結局プレフィックス頼みですね。。。
(より良い方法がありましたらご教授願います。)