外部キー制約を設定したマイグレーションでエラーが発生する原因と対処法

はじめに

【入門】Laravelチュートリアル - 掲示板を作成してみよう | 実践的Web開発メソッド

こちらの手順に従ってマイグレーションファイルを作成しマイグレートを行おうとしたところ、以下のエラーが出力されました。

$ php artisan migrate
Migration table created successfully.
Migrating: 2020_02_23_164117_create_posts_table
Migrated:  2020_02_23_164117_create_posts_table (0.01 seconds)
Migrating: 2020_02_23_164211_create_comments_table

   Illuminate\Database\QueryException  : SQLSTATE[HY000]: General error: 3780 Referencing column 'post_id' and referenced column 'id' in foreign key constraint 'comments_post_id_foreign' are incompatible. (SQL: alter table `comments` add constraint `comments_post_id_foreign` foreign key (`post_id`) references `posts` (`id`))

  at /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:669
    665|         // If an exception occurs when attempting to run a query, we'll format the error
    666|         // message to include the bindings with SQL, which will make this exception a
    667|         // lot more helpful to the developer instead of just the database's errors.
    668|         catch (Exception $e) {
  > 669|             throw new QueryException(
    670|                 $query, $this->prepareBindings($bindings), $e
    671|             );
    672|         }
    673| 

  Exception trace:

  1   PDOException::("SQLSTATE[HY000]: General error: 3780 Referencing column 'post_id' and referenced column 'id' in foreign key constraint 'comments_post_id_foreign' are incompatible.")
      /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:463

  2   PDOStatement::execute()
      /Users/user/Products/MyProject/vendor/laravel/framework/src/Illuminate/Database/Connection.php:463

  Please use the argument -v to see more details.

マイグレーション内容

今回実行しようとしたマイグレーションファイルは以下の通りです。
詳しくは上記リンクを参照してください。

database/migrations/2020_02_23_171858_create_posts_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreatePostsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('posts', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->string('title',50);
            $table->text('body');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('posts');
    }
}

database/migrations/2020_02_23_171919_create_comments_table.php

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateCommentsTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('comments', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedInteger('post_id');
            $table->text('body');
            $table->timestamps();

            $table->foreign('post_id')->references('id')->on('posts');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('comments');
    }
}

ひとつのpostに複数のcommentsを関連づられるよう、commentsテーブルに外部キー制約を設定しています。

原因

外部キーを呼び出す側(comments.post_id)と呼び出される側(posts.id)のデータ型が一致していないため。
※ここではunsignedは無視してください。

外部キーを呼び出す側(comments.post_id

$table->unsignedInteger('post_id');   # int unsigned

呼び出される側(posts.id

$table->bigIncrements('id');          # bigint

対処

外部キーを呼び出す側(comments.post_id)を以下のように変更します。

$table->unsignedBigInteger('post_id');   # bigint unsigned

関連記事

開発環境(ローカルストレージ)と本番環境(Amazon S3)にトリミング+リサイズした画像を保存する方法
# はじめに 以前、以下の記事を書きました。 - [開発環境と本番環境で画像のアップロード先を分岐する方法 \- AUTOVICE](https://www.autovice.jp/articles/68) - [ローカルやAmazon [...]
2020年3月7日 11:56
Laravel Mixの仕組みをわかりやすく解説:CSSをSASS/SCSSで記述する方法
# はじめに Laravel Mixの仕組みをわかりやすく解説します。Laravel Mixを使ってアセットコンパイルを行うことで、SASS/SCSSでCSSを記述できるようになります。 # Laravel Mixの仕組み まずはじめに、 [...]
2020年3月6日 9:25
【Laravel 6.x】Laravelプロジェクトの名称を変更する方法
# はじめに あまりないケースではありますが、一度作成したLaravelプロジェクトの名称を変更する方法を解説します。ここで言うLaravelプロジェクトの名称とは、以下のコマンドの`Sample`のことを指します。 ```terminal [...]
2020年3月4日 16:24
【Laravel】ローカルディスクやAmazon S3にアップロードした画像をビューで表示する方法
# はじめに 本記事では、ローカルディスクやAmazon S3にアップロードした画像をビューで表示する方法について説明しています。 なお、本記事では画像のアップロードする方法については説明していません。本記事は既に実装済みの画像アップロード [...]
2020年3月4日 15:44
【Laravel】Amazon S3へのアップロードが「403 Access Denied」で失敗する原因と対処方法
# はじめに LaravelでAmazon S3へ画像アップロードする処理を実装し、いざアップロードしようとしたところ、以下のエラーが出て失敗しました。 ``` Error executing "PutObject" on "https: [...]
2020年3月4日 13:33
開発環境と本番環境で画像のアップロード先を分岐する方法
# はじめに この記事では、以下の方針で画像のアップロード先を分岐する方法について解説しています。 - 開発環境:ローカル(storage/app/public/) - 本番環境:Amazon S3 # 事前準備 AWSに未登録の [...]
2020年3月4日 12:52
独自ポリシーの導入手順と注意点(ハマリポイント)を解説
# はじめに ユーザーと記事を関連付けておいて、編集や削除は記事の作成者のみ許可したいときにはポリシーを作成します。今回はポリシーの導入手順と注意点(ハマリポイント)を解説します。 # 導入手順 ## ポリシー作成 ターミナルで以下 [...]
2020年3月1日 10:32
ユーザー認証機能の導入手順と生成されたフォームを日本語化する方法を解説
# はじめに Laravelではユーザー認証機能の導入が簡単にできてしまいます。この記事ではLaravelプロジェクトにユーザー認証機能を追加する手順と、生成されたフォーム(デフォルトでは英語)を日本語化する方法を解説します。 # 前提 [...]
2020年2月29日 13:54