10
16

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 1 year has passed since last update.

Laravelで既存のテーブルに外部キー制約を追加・削除する方法

Last updated at Posted at 2021-08-04

暇なときに予定を探せるアプリyoteiPickerをリリースしました。

この記事では、Laravelのマイグレーションですでにあるテーブルに外部キー制約を追加する方法を解説します。

Laravelのバージョンは6系です。
mysqlのバージョンは5.7系です。

>>フリーランスも対象!エンジニア転職におすすめなサイト5選

以下のようなテーブルがあったとします。

booksテーブル
book_id
book_name

categoriesテーブル
category_id
category_name

すでにどちらのマイグレーションも実行済みだけど、booksテーブルにcategory_idと外部キー制約を追加したいってときに使える記事です。

【完成系】
booksテーブル
book_id
book_name
category_id(外部キー制約)

まずはカラム追加のマイグレーションファイルを作成します。

php artisan make:migration add_category_id_to_books_table --table=books

マイグレーションファイルを編集します。

<?php

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

class AddCategoryIdToBooksTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            // カラム追加
            $table->bigInteger('category_id')->unsigned()->after('book_name');
            // カラムの外部キー制約追加
            $table->foreign('category_id')->references('category_id')->on('categories')->OnDelete('cascade');
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::table('books', function (Blueprint $table) {
            // 外部キー制約の削除
            $table->dropForeign('books_category_id_foreign');
            // カラムの削除
            $table->dropColumn('category_id');
        });
    }
}

マイグレーションを実行します。

php artisan migrate

これで、外部キー制約のカラムを追加できました。
スクリーンショット 2021-08-04 21.35.38.png

## 解説

$table->bigInteger('category_id')->unsigned()->after('book_name');

bigInteger('category_id')はcategoriesテーブルのcategory_idと型を合わせる必要があります。

categoriesテーブル
category_id
category_name

マイグレーションファイルでは、デフォルトで以下のように作成されるからです。

<?php

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

class CreateCategoriesTable extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('categories', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
        });
    }

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

categoriesテーブルのcategory_idはbigIncrementsなので、bigIntegerにしているってわけですね。

laravel5.8以前の場合は、categoriesテーブルのcategory_idはincrementsで作成されるでしょう。その場合は、integer('category_id')にする必要があります。

unsigned()->after('book_name')のunsigned()は符号なし、つまりマイナスの数字は許容しない、'after('book_name')'でbook_nameカラムの後にcategory_idカラムが追加されるように指定しています。

まとめると、

$table->bigInteger('category_id')->unsigned()->after('book_name');

category_idのカラムの型はbigIntegerで符号なし、book_nameカラムの後にcategory_idカラムを追加って意味です。

$table->foreign('category_id')->references('category_id')->on('categories')->OnDelete('cascade');
foreign('category_id')->references('category_id')->on('categories')

外部キーはcategory_idで、参照するのはcategoriesテーブルのcategory_idだよって意味です。

OnDelete('cascade')は決まり文句みたいなもので、
外部キー制約を CASCADE に設定することで、紐づいているレコードも含め一括で削除可能です。

            // 外部キー制約の削除
            $table->dropForeign('books_category_id_foreign');
            // カラムの削除
            $table->dropColumn('category_id');

downにはrollbackした時の操作を書きます。
dropForeign('books_category_id_foreign')この部分ですが、
外部キーを追加するテーブル名_外部キー名_foreignとしてください。

downに外部キー制約の削除とカラムの削除を書かないと、rollbackできずにマイグレーションエラーとなりますので、ご注意を。

他にも記事書いているので、ぜひプロフィールからご参照ください。
・マイグレーション
・クエリビルダなど
書いています。

##既存テーブルから外部キー制約の削除
すでに外部キー制約のカラムがあるテーブルから外部キー制約のカラムを削除したいと思います。

まずはマイグレーションファイルを作成。

php artisan make:migration drop_category_id_to_books_table --table=books

マイグレーションファイルの編集
upに外部キー制約削除をdownにはrollbackしたときに元に戻す処理を書きます。

    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            // 外部キー制約の削除
            $table->dropForeign('books_category_id_foreign');
            // カラム削除
            $table->dropColumn('category_id');
        });
    }

    public function down()
    {
        Schema::table('books', function (Blueprint $table) {
            // カラムの追加
            $table->unsignedBigInteger('category_id')->after('user_id');
            // 外部キーの追加
            $table->foreign('category_id')->references('category_id')->on('categories');
        });
    }

##既存テーブルからカラムは削除したくないけど外部キー制約は解除したい場合
マイグレーションファイルを作成
php artisan make:migration drop_foreign_key_to_books_table --table=books

マイグレーションファイルを編集

    public function up()
    {
        Schema::table('books', function (Blueprint $table) {
            // 外部キー制約の削除
            $table->dropForeign('books_category_id_foreign');
        });
    }

    public function down()
    {
        Schema::table('books', function (Blueprint $table) {
            // 外部キーの追加
            $table->foreign('category_id')->references('category_id')->on('categories');
        });
    }

データベースを確認すると、外部キー名などが残ってしまいます。その場合は、以下のSQLを実行すれば外部キー名なども消えます。

データベースでSQLを実行

alter table books
 drop index books_category_id_foreign

暇なときに予定を探せるアプリyoteiPickerをリリースしました。

>>Laravelのマイグレーションが怖くない【作成・カラムの追加・削除】
>>【Laravelクエリビルダ】複数のカラムをgroupByでグループ化させる

>>フリーランスも対象!エンジニア転職におすすめなサイト5選

10
16
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
10
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?