【Laravel】 General error: 1215 Cannot add foreign key constraint 【エラー】

# はじめに

この記事では、Laravelの学習中に発生したエラーとその解決方法を覚え書きしておきます。

# 環境
Laravel 5.8
MAMP 5.7
phpMyAdmin 4.9.3

# 今回の状況
マイグレーションファイルをいくつか作成、``php artisan migrate``を実行した際、下記のエラーが発生。

``` :発生したエラー
General error: 1215 Cannot add foreign key constraint
```

## 先に結論

外部キー制約では、参照元のカラムと参照先のカラムの型が一致する必要がある。
→それぞれの型に違いがあったためエラーが発生していた。

# 対処方法
各カラムのデータ型を揃えることで解決。

## ざっくり手順
``php artisan migrate:rollback``
↓
マイグレーションファイルを修正
↓
``php artisan migrate``
で無事マイグレーションできた。

## 具体的な対応
▼外部キー制約を設定するマイグレーションファイル
```php:2023_01_21_152852_add_foreign_key_to_drills
Schema::table('drills', function (Blueprint $table) {
    $table->foreign('category_id')
        ->references('id')
        ->on('categories');
    $table->foreign('problem_id')
        ->references('id')
        ->on('problems');
    $table->foreign('user_id')
        ->references('id')
        ->on('users');
});
```
上記のマイグレーション時にエラーが発生。
drillsテーブルを作成した際、``category_id``、``problem_id``、``user_id``をintegerで作成していたため、外部連携させるカラムと型(Type)が異なっていた。

▼上記のdrillsテーブルを作成するマイグレーションファイル(問題のファイル)
```php:2023_01_21_144721_create_drills_table (修正前)
Schema::create('drills', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('title');
    $table->integer('category_id');
    $table->integer('problem_id');
    $table->integer('user_id');
    $table->timestamps();
});
```
```
mysql> desc drills;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| title       | varchar(255)        | NO   |     | NULL    |                |
| category_id | int(11)             | NO   | MUL | NULL    |                |
| problem_id  | int(11)             | NO   | MUL | NULL    |                |
| user_id     | int(11)             | NO   | MUL | NULL    |                |
| created_at  | timestamp           | YES  |     | NULL    |                |
| updated_at  | timestamp           | YES  |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+
```

今回、各連携先のカラムは``bigIncrements``で作成されている。
そのため、連携元であるdrillsテーブルの各カラムは``unsignedBigInteger``で作成する必要がある。
(上記では``integer``で作成されており、型が異なるためエラーになっていた)

```php:2023_01_21_144721_create_drills_table (修正後)
Schema::create('drills', function (Blueprint $table) {
    $table->bigIncrements('id');
    $table->string('title');
    $table->unsignedBigInteger('category_id');
    $table->unsignedBigInteger('problem_id');
    $table->unsignedBigInteger('user_id');
    $table->timestamps();
});
```
```
mysql> desc drills;
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| title       | varchar(255)        | NO   |     | NULL    |                |
| category_id | bigint(20) unsigned | NO   | MUL | NULL    |                |
| problem_id  | bigint(20) unsigned | NO   | MUL | NULL    |                |
| user_id     | bigint(20) unsigned | NO   | MUL | NULL    |                |
| created_at  | timestamp           | YES  |     | NULL    |                |
| updated_at  | timestamp           | YES  |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+
```

外部キー制約を設定するマイグレーションファイルのうち、
``category_id``、``problem_id``、``user_id``の各カラムについて、
``integer``→``unsignedBigInteger``
と修正することで、各カラムの型も
``int(11)``→``bigint(20) unsigned``
となり、型が一致するので、外部キー制約を設定することができるようになる。


# 参考記事
[Laravel | migrationの作成と実行方法 - わくわくBank](URL "https://www.wakuwakubank.com/posts/450-laravel-migration/")