メインコンテンツへスキップ

概要

Eloquentモデルはインスタンス化のたびに「起動処理(boot)」と「初期化処理(initialize)」を実行します。トレイトにこれらのメソッドを定義しておくと、モデルがそのトレイトを use するだけで自動的に呼び出されます。 この仕組みを使うことで、モデルに機能を注入するトレイトをクリーンに実装できます。Laravelフレームワーク自体も SoftDeletes などの多くのトレイトでこのパターンを活用しています。

boot と initialize の違い

bootXxx()initializeXxx()
呼び出しタイミングモデルクラスの最初の起動時(クラスごとに1回)インスタンス生成のたび
メソッド種別staticインスタンスメソッド
用途イベントリスナー登録、グローバルスコープ追加などデフォルト値設定、プロパティ初期化など

ネーミング規約

bootXxx()

トレイト名の末尾に boot プレフィックスをつけた static メソッドを定義すると、モデル起動時に一度だけ呼ばれます。
namespace App\Models\Concerns;

trait HasSlug
{
    public static function bootHasSlug(): void
    {
        static::creating(function ($model) {
            if (empty($model->slug)) {
                $model->slug = str($model->name)->slug()->toString();
            }
        });
    }
}
モデル側での使用:
use App\Models\Concerns\HasSlug;

class Article extends Model
{
    use HasSlug;
    // bootHasSlug() は自動的に呼び出される
}

initializeXxx()

トレイト名の末尾に initialize プレフィックスをつけたインスタンスメソッドを定義すると、モデルの new のたびに呼ばれます。
namespace App\Models\Concerns;

trait HasDefaultStatus
{
    public function initializeHasDefaultStatus(): void
    {
        $this->attributes['status'] ??= 'draft';
    }
}
$casts への動的な追加にも使えます:
trait HasMetadata
{
    public function initializeHasMetadata(): void
    {
        $this->mergeCasts([
            'metadata' => 'array',
        ]);
    }
}

PHP Attribute による明示的な指定

Laravel 11 以降、ネーミング規約に頼らず PHP Attribute で明示的にメソッドを指定できます。
Attribute対象
#[Boot]クラス起動時に一度だけ実行するメソッド
#[Initialize]インスタンス生成のたびに実行するメソッド
use Illuminate\Database\Eloquent\Attributes\Boot;
use Illuminate\Database\Eloquent\Attributes\Initialize;

trait HasAuditLog
{
    #[Boot]
    public static function registerAuditListeners(): void
    {
        static::created(function ($model) {
            AuditLog::record('created', $model);
        });

        static::updated(function ($model) {
            AuditLog::record('updated', $model);
        });
    }

    #[Initialize]
    public function setAuditDefaults(): void
    {
        $this->attributes['audit_enabled'] ??= true;
    }
}
PHP Attribute を使うと、メソッド名がトレイト名に縛られないため、意味のある名前をつけられます。複数の #[Boot] メソッドや #[Initialize] メソッドを同じトレイトに定義することも可能です。

実用例:パッケージ開発での活用

グローバルスコープの自動追加

trait HasTenant
{
    public static function bootHasTenant(): void
    {
        static::addGlobalScope(new TenantScope);
    }
}

デフォルトキャスト追加

trait HasJsonSettings
{
    public function initializeHasJsonSettings(): void
    {
        $this->mergeCasts([
            'settings' => 'array',
        ]);
    }
}

Eloquentイベントで自動処理

trait Archivable
{
    #[Boot]
    public static function bootArchivable(): void
    {
        static::deleting(function ($model) {
            Archive::store($model->toArray());
        });
    }
}

Laravelフレームワーク内の例

Laravelフレームワーク自身も多くのトレイトでこのパターンを採用しています。
トレイトメソッド処理内容
SoftDeletesbootSoftDeletes()ソフトデリート用グローバルスコープの追加
HasFactorybootHasFactory()特になし(スコープ外の仕組み)
HasUlidsbootHasUlids()creating イベントで ULID を自動セット
HasUuidsbootHasUuids()creating イベントで UUID を自動セット
これらを参考実装として読むと、パターンの理解が深まります。

注意点

モデルキャッシュのクリア

boot* はクラスごとに一度しか実行されないため、テスト環境では注意が必要です。Model::clearBootedModels() で起動済みキャッシュをリセットできます。
// テスト後にモデルのブート状態をリセット
protected function tearDown(): void
{
    Model::clearBootedModels();
    parent::tearDown();
}

実行順序

同一モデルに複数のトレイトが use されている場合、bootXxx() / initializeXxx() はPHPのトレイト解決順(宣言順)で呼ばれます。依存関係がある場合は use の順序に注意してください。

まとめ

パターン方法適用場面
クラス起動時処理static bootXxx() または #[Boot]イベント登録、グローバルスコープ追加
インスタンス初期化initializeXxx() または #[Initialize]デフォルト値、キャスト追加
トレイトに bootXxx() / initializeXxx() を実装しておくと、モデルへの機能注入が use 一行で済むようになります。パッケージでモデルに機能を追加する際の定番パターンです。
最終更新日 2026年7月13日