はじめに
複数のテーブルに同じカラムを持たせるとき、
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のクラスが生成されます。
<?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定義を記述します。
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
に登録します。
'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つのカラムを定義してくれています。
参考