Laravel 外部キーを設定 Cannot add foreign key
Laravel学習中に詰まったので記憶定着も兼ねてメモ。
症状
Authを使用したユーザー認証を導入し、usersテーブルがある。そこに、投稿用のpostsテーブルを用意。usersテーブルのPKであるidに対してpostsテーブルのuser_idに外部キーを設定する。
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
#--省略--
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('user_id');
$table->string('title');
$table->string('content');
$table->timestamps();
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
% php artisan migrate
結果
General error: 1215 Cannot add foreign key constraint
(SQL: alter table `posts` add constraint `posts_user_id_foreign`
foreign key (`user_id`) references `users` (`id`) on delete cascade)
---省略---
677▕ catch (Exception $e) {
➜ 678▕ throw new QueryException(
679▕ $query, $this->prepareBindings($bindings), $e
680▕ );
681▕ }
682▕
---
調べてみた
外部キーが設定できないエラーなので、原因はUsersのidか、Postsの外部キーの設定のどちらかと考えるのが普通だと思う。一見外部キー制約の方には問題がなさそうだったため、まずはUsersのidから調べることにした。
そもそもid( )ってなんだ
$table->id( )とあるが、このメソッドはなんだろうか。まあ、調べなくてもidを付与する的な何かということはわかる。ただ、その中で都合が悪いためにエラーが起きている可能性はある。
id( )はどこに定義してあるのか
id( )は、\$tableに対して呼び出されている。$tableはBlueprint
を引っ張っている。
Schema::create('posts', function (Blueprint $table){
Blueprintは、useで指定してあるIlluminate\Database\Schema\Blueprint
にあるっぽいので、行ってみた。(ちなみに、Illuminateは、vernder/laravel/frameworkにある)
あった。
public function id($column = 'id')
{
return $this->bigIncrements($column);
}
超絶シンプル。しかし、これだとbigIncrementsが実行されていることしかわからない。
$thisって書いてあるので、ここからさらにbigIncrementsを探す。
public function bigIncrements($column)
{
return $this->unsignedBigInteger($column, true);
}
これもまたシンプル。だが、ここでもunsignedBigIntegerが実行されているだけ。
と、思いきや、よく考えると、unsignedじゃないか!!
ということで、ここで型の不一致説が濃厚になる。
外部キー制約を設けたuser_idは、単純なinteger型。
id( )をinteger型にするのは現実的ではないので、user_idにunsignedを付与してみる。
$table->integer('user_id')->unsigned();
% php artisan migrate:reset
% php artisan migrate
一度実行しているので、リセットしてからマイグレート。(ただし、自分の場合はresetでpostsテーブルがドロップされない事件が起きていたので、mysqlから直接drop table postsで行った。)
Migrating: 20xx_xx_xx_000000_create_users_table
Migrated: 20xx_xx_xx_000000_create_users_table (27.76ms)
Migrating: 20xx_xx_xx_100000_create_password_resets_table
Migrated: 20xx_xx_xx_100000_create_password_resets_table (20.34ms)
Migrating: 20xx_xx_xx_000000_create_failed_jobs_table
Migrated: 20xx_xx_xx_000000_create_failed_jobs_table (19.75ms)
Migrating: 20xx_xx_xx_084051_create_posts_table
Migrated: 20xx_xx_xx_084051_create_posts_table (27.74ms)
成功した。
最終的には、idメソッドではなくincrementsメソッドを使用したが、同じくunsignedが付与される。
public function up()
{
Schema::create('users', function (Blueprint $table) {
$table->increments('id');
$table->string('name');
$table->string('email')->unique();
$table->timestamp('email_verified_at')->nullable();
$table->string('password');
$table->rememberToken();
$table->timestamps();
});
}
public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->engine = 'InnoDB';
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->string('title');
$table->string('content');
$table->timestamps();
// Set user ID to foreign key and automatic updating
$table->foreign('user_id')
->references('id')
->on('users')
->onDelete('cascade');
});
}
以上。
Author And Source
この問題について(Laravel 外部キーを設定 Cannot add foreign key), 我々は、より多くの情報をここで見つけました https://qiita.com/en_tokiya/items/896b0c0edfc631f9302c著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .