Laravelのmigrationで外部キー設定が上手くいかない時の対処法

#状況
Laravelでmigrationファイルを作成、カラムの追加、外部キーを設定してmigrationしようとすると外部キーの設定が上手くいかなかった。

usersテーブルのidをexpensesテーブルuser_idを、categoryテーブルのidがexpensesテーブルのcategoy_idが参照するうに設定したかったが、user_idの方だけ失敗した。

因みにusersテーブルは`php artisan ui react --auth`でログイン／ユーザー登録スカフォールド(React)を生成した時に自動的に作成されたテーブル。

#試したこと

categoryテーブルのidはincrementsで定義しているため、型がunsignedになるので注意と書いてあったのでexpensesテーブルのcategory_idはunsignedを明示的に定義した。こっちは上手くいった。

初回のmigrationでは以下のファイルを使いました。

```php:create_users_table.php
//これは自動的に作成されたファイル。何もいじってない。
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();
        });
    }
```

```php:create_categories_table.php
//idをIncrementsで定義
public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
        });
    }
```

```php:create_expenses_table.php

public function up()
    {
        Schema::create('expenses', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->integer('price');

            //unsignedIntegerで定義して外部キーを設定
            $table->unsignedinteger('category_id');
            $table->foreign('category_id')->references('id')->on('categories');

            //Integerで定義して外部キーを設定
            $table->integer('user_id');
            $table->foreign('user_id')->references('id')->on('users');
            $table->timestamps();
        });
    }
```

こんな感じのテーブルができてました。

```
//usersテーブル
+-------------------+---------------------+------+-----+---------+----------------+
| Field             | Type                | Null | Key | Default | Extra          |
+-------------------+---------------------+------+-----+---------+----------------+
| id                | bigint(20) unsigned | NO   | PRI | NULL    | auto_increment |
| name              | varchar(255)        | NO   |     | NULL    |                |
| email             | varchar(255)        | NO   | UNI | NULL    |                |
| email_verified_at | timestamp           | YES  |     | NULL    |                |
| password          | varchar(255)        | NO   |     | NULL    |                |
| remember_token    | varchar(100)        | YES  |     | NULL    |                |
| created_at        | timestamp           | YES  |     | NULL    |                |
| updated_at        | timestamp           | YES  |     | NULL    |                |
+-------------------+---------------------+------+-----+---------+----------------+

//categoryテーブル
+-------+------------------+------+-----+---------+----------------+
| Field | Type             | Null | Key | Default | Extra          |
+-------+------------------+------+-----+---------+----------------+
| id    | int(10) unsigned | NO   | PRI | NULL    | auto_increment |
| name  | varchar(255)     | NO   |     | NULL    |                |
+-------+------------------+------+-----+---------+----------------+

//expensesテーブル
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| title       | varchar(255)        | NO   |     | NULL    |                |
| price       | int(11)             | NO   |     | NULL    |                |
| category_id | int(20) unsigned    | NO   |     | NULL    |                |
| user_id     | int(20)             | NO   | MUL | NULL    |                |
| created_at  | timestamp           | YES  |     | NULL    |                |
| updated_at  | timestamp           | YES  |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+
```

#原因と対処法

usersテーブルでidは`$table->id();`で定義されているためデータ型は「bigint(20) unsigned」になっていたためexpensesテーブルのusers_idのデータ型(int(20)と不一致が起きてしまっていた。


修正後

```php:create_expenses_table.php
    public function up()
    {
        Schema::create('expenses', function (Blueprint $table) {
            $table->increments('id');
            $table->string('title');
            $table->integer('price');
            $table->unsignedinteger('category_id');
            $table->foreign('category_id')->references('id')->on('categories');

            //unsignedBigintegerに変更
            $table->unsignedBiginteger('user_id');
            $table->foreign('user_id')->references('id')->on('users');
            $table->timestamps();
        });
    }
```

データ型もしっかり合っています。

```
usersテーブル
+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int(10) unsigned    | NO   | PRI | NULL    | auto_increment |
| title       | varchar(255)        | NO   |     | NULL    |                |
| price       | int(11)             | NO   |     | NULL    |                |
| category_id | int(10) unsigned    | NO   | MUL | NULL    |                |
| user_id     | bigint(20) unsigned | NO   | MUL | NULL    |                |
| created_at  | timestamp           | YES  |     | NULL    |                |
| updated_at  | timestamp           | YES  |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+
```
ちゃんと外部キーの設定もできました。

```
mysql > show create table expenses;

| expenses | CREATE TABLE `expenses` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `title` varchar(255) COLLATE utf8mb4_unicode_ci NOT NULL,
  `price` int(11) NOT NULL,
  `category_id` int(10) unsigned NOT NULL,
  `user_id` bigint(20) unsigned NOT NULL,
  `created_at` timestamp NULL DEFAULT NULL,
  `updated_at` timestamp NULL DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `expenses_category_id_foreign` (`category_id`),
  KEY `expenses_user_id_foreign` (`user_id`),
  CONSTRAINT `expenses_category_id_foreign` FOREIGN KEY (`category_id`) REFERENCES `categories` (`id`),
  CONSTRAINT `expenses_user_id_foreign` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci |
```