[Laravel 8] マイグレーション実行時、"Foreign key constraint is incorrectly formed" エラーがでるときの解決法


Laravel 8 でマイグレーション実行後に、**errno: 150 "Foreign key constraint is incorrectly formed"** というエラーが発生したときの対処法を( ..)φメモメモ。

このエラー、直訳すると**「外部キー制約が正しく形成されていない」**ということらしい…どういうことや (;・∀・)

調べてみると、<font color="red">**「外部キーの参照先」と「参照元」のデータ型が一致していない**</font> ためエラーが発生するみたいです。

## このエラーって、どういう状況でおこるの？
このエラーがおこる状況を再現してみたいと思います。
今回は、例として **`users` テーブルの `id` カラムを参照する、`articles` テーブルの `user_id` カラム** を構築してみましょう。

まず、最初から設定済みの `users` テーブルのマイグレーションファイル（ `database/migrations/2014_10_12_000000_create_users_table.php` ）を確認してください。

```php:database/migrations/2014_10_12_000000_create_users_table.php
// 略

class CreateUsersTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    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();
        });
    }

    // 略
}
```

次に、`articles` マイグレーションファイルの設定です。コマンドで以下を打ち込むとArticleモデルと一緒に、マイグレーションファイルが作成されます。新しく作成された`articles` テーブル用のマイグレーションファイルには、下記コードのように **`// 追加部分`** と書いてある行を追記してみてください。

```command
php artisan make:model Article -m 
```

```php:database/migrations/2021_07_10_xxxxxx_create_articles_table.php
// 略

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();
            $table->text('body'); // 追加部分
            $table->bigInteger('user_id'); // 追加部分
            $table->foreign('user_id')->references('id')->on('users'); // 追加部分
            $table->timestamps();
        });
    }

    // 略
}
```

さて、マイグレーションファイルの準備が整ったので、コマンドでマイグレーションの実行をしてみましょう。以下のコマンドを打ち込んでください。

```
php artisan migrate
```

すると、どうでしょう？　**errno: 150 ”Foreign key constraint is incorrectly formed”** というエラーが表示されましたでしょうか？これが、<font color="red">**「外部キーの参照先」と「参照元」のデータ型が一致していない**</font> ために表示されるエラーです。

今回のマイグレーションは、

- **「外部キーの参照先」**を `users` テーブルの `id カラム`
- **「参照元」**を `article` テーブルの `user_id カラム`

としています。
双方のカラムのデータ型も確認してみましょう。

- `users` テーブルの `id カラム`のデータ型
 - AUTO_INCREMENT
 - bigint(20)
 - UNSIGNED

- `articles` テーブルの `user_id カラム`のデータ型
 - AUTO_INCREMENT
 - bigint(20)

上記のデータ型を見て分かるように、`articles` テーブルの `user_id カラム` には `UNSIGNED` 属性が足りていません。これが原因でエラーが発生していたのです。なので、今回の例では、エラーをなくすために、以下のようにマイグレーションファイルを修正します。

```diff:database/migrations/2021_07_10_xxxxxx_create_articles_table.php
// 略

class CreateArticlesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('articles', function (Blueprint $table) {
            $table->id();
            $table->text('body');
-           $table->bigInteger('user_id');
+           $table->unsignedBigInteger('user_id');
            $table->foreign('user_id')->references('id')->on('users');
            $table->timestamps();
        });
    }

    // 略
}
```

このように、`$table->bigInteger('user_id');` を`$table->unsignedBigInteger('user_id');` にすることで、参照先の `user` テーブルの `id` カラムとデータ型が一致します。あとは、もう一度データベースをリセットして、コマンドで `php artisan migrate` を打ち込んでみると、エラーがでずに処理されていると思います。

**"Foreign key constraint is incorrectly formed"** というエラーが発生したら、データ型を揃える。

覚えておきます( ..)φメモメモ