LoginSignup
18
12

More than 3 years have passed since last update.

【Laravel】migrationで複数テーブルの共通カラム定義を1か所に共通化する方法

Posted at

はじめに

複数のテーブルに同じカラムを持たせるとき、
migrationでテーブル1つ1つに同じカラム定義を記述するのは面倒です。

例えば、よく使われるのは
created_at、created_by、updated_at、updated_by、deleted_at、deleted_byなどです。

普通にやると各テーブルごとに上記カラム定義を記述することになりますね。

    public function up()
    {
        Schema::create('foo_table', function (Blueprint $table) {
            $table->id();

            $table->timestamp('created_at')->nullable();
            $table->unsignedBigInteger('created_by')->nullable();
            $table->timestamp('updated_at')->nullable();
            $table->unsignedBigInteger('updated_by')->nullable();
            $table->timestamp('deleted_at')->nullable();
            $table->unsignedBigInteger('deleted_by')->nullable();
        });

        Schema::create('bar_table', function (Blueprint $table) {
            $table->id();

            $table->timestamp('created_at')->nullable();
            $table->unsignedBigInteger('created_by')->nullable();
            $table->timestamp('updated_at')->nullable();
            $table->unsignedBigInteger('updated_by')->nullable();
            $table->timestamp('deleted_at')->nullable();
            $table->unsignedBigInteger('deleted_by')->nullable();
        });

        Schema::create('baz_table', function (Blueprint $table) {
            $table->id();

            $table->timestamp('created_at')->nullable();
            $table->unsignedBigInteger('created_by')->nullable();
            $table->timestamp('updated_at')->nullable();
            $table->unsignedBigInteger('updated_by')->nullable();
            $table->timestamp('deleted_at')->nullable();
            $table->unsignedBigInteger('deleted_by')->nullable();
        });
    }

※Laravelは$table->timestamps();という機能を提供しており、created_atとupdated_atだけは共通で定義可能です

このように全テーブルに毎回共通カラム定義を羅列するのは面倒です。
共通コード1か所だけにそのカラム定義を記述し、
migrationではそれを利用するだけの形が望ましいです。
こんなイメージ。

    public function up()
    {
        Schema::create('foo_table', function (Blueprint $table) {
            $table->id();

            $table->systemColumns(); // 共通カラム定義
        });

        Schema::create('bar_table', function (Blueprint $table) {
            $table->id();

            $table->systemColumns(); // 共通カラム定義
        });

        Schema::create('baz_table', function (Blueprint $table) {
            $table->id();

            $table->systemColumns(); // 共通カラム定義
        });
    }

$table->systemColumns();を呼ぶだけで6つの共通カラムが定義できる状態です。

Laravelではmacroという機能を利用してBlueprintクラスを拡張することで
いい感じにできるので、今回はその方法を紹介します。

macroとは

macroとは、Laravelフレームワーク自体が提供しているクラスに
好きなメソッドを追加することができる機能です。

例えば、
Requestクラスにユーザーエージェントを判定するメソッドを追加してみたり、
Carbonクラスに特定のフォーマットに変換するメソッドを追加してみたり、
Laravelのクラスに自由にメソッドを追加できます。

macroの詳しい使い方や
macro利用可能なクラスなどについては
こちらの記事が非常にわかりやすく解説していますのでご参考に。

今回は、migrationで利用されている
Blueprintクラスにこのmacroで機能追加することによって
共通カラムのコード共通化を行います。

Blueprintにmacro追加

まずはBlueprintのmacroを定義するために
サービスプロバイダを新しく作ります。

makeコマンド実行。

php artisan make:provider BlueprintServiceProvider

すると下記のようにBlueprintServiceProviderのクラスが生成されます。

app/Providers/BlueprintServiceProvider.php
<?php

namespace App\Providers;

use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\ServiceProvider;

class BlueprintServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

このbootメソッドに、macro定義を記述します。

app/Providers/BlueprintServiceProvider.php
    public function boot()
    {
        Blueprint::macro('systemColumns', function () {
            $this->timestamp('created_at')->nullable();
            $this->unsignedBigInteger('created_by')->nullable();
            $this->timestamp('updated_at')->nullable();
            $this->unsignedBigInteger('updated_by')->nullable();
            $this->timestamp('deleted_at')->nullable();
            $this->unsignedBigInteger('deleted_by')->nullable();
        });
    }

これでBlueprintクラスにsystemColumnsというメソッドが追加されました。

このサービスプロバイダを有効にするため、
config/app.phpに登録します。

config/app.php
'providers' => [
    // 中略
    App\Providers\BlueprintServiceProvider::class,
];

これでBulueprintへのmacro定義完了です。

migrationでmacroを利用

あとは、冒頭で見せたように、
migrationでこのmacroを呼び出すだけです。

    public function up()
    {
        Schema::create('foo_table', function (Blueprint $table) {
            $table->id();

            $table->systemColumns(); // 共通カラム定義
        });

        Schema::create('bar_table', function (Blueprint $table) {
            $table->id();

            $table->systemColumns(); // 共通カラム定義
        });

        Schema::create('baz_table', function (Blueprint $table) {
            $table->id();

            $table->systemColumns(); // 共通カラム定義
        });
    }

migrationでは$table->systemColumns();と書いているだけですが、
内部的には先ほど定義したmacroのsystemColumnsメソッドが呼び出されていて
created_at、created_by、updated_at、updated_by、deleted_at、deleted_by
の6つのカラムを定義してくれています。

参考

18
12
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
18
12