0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

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

Last updated at Posted at 2020-03-13

状況

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では以下のファイルを使いました。

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();
        });
    }
create_categories_table.php
//idをIncrementsで定義
public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
        });
    }
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)と不一致が起きてしまっていた。

修正後

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 |
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?