Laravelのルートモデルバインディング

概要

ルートモデルバインディングとは、URLパラメータからEloquentモデルのインスタンスを自動的に解決する仕組みです。
コントローラで手動に find() を呼び出す冗長なコードをフレームワーク側に委譲できます。

暗黙的バインディング

最もシンプルな形式です。
コントローラのメソッド引数の型ヒントとルートパラメータ名が一致するだけで、Laravelが自動的にモデルを解決します。

// routes/web.php
Route::get('/posts/{post}', [PostController::class, 'show']);

// PostController.php
public function show(Post $post): Response
{
    return response()->json($post);
}

デフォルトでは主キー(id)を使ってモデルを検索します。
レコードが見つからない場合は自動的に404レスポンスを返します。

解決するキーのカスタマイズ

スラッグやUUIDなど、id 以外のカラムで解決したい場合は2通りの方法があります。

ルート定義での指定

Route::get('/posts/{post:slug}', [PostController::class, 'show']);

モデルでのオーバーライド

// Post.php
public function getRouteKeyName(): string
{
    return 'slug';
}

明示的バインディング

RouteServiceProvider または AppServiceProviderboot() メソッドでバインディングを明示的に定義します。
カスタムクエリや複雑なロジックが必要な場合に有効です。

// AppServiceProvider.php
public function boot(): void
{
    Route::model('post', Post::class);

    // または任意のロジックでモデルを解決する
    Route::bind('post', function (string $value): Post {
        return Post::where('slug', $value)->firstOrFail();
    });
}

スコープ付きバインディング

ネストしたルートで親子関係を強制したい場合に使います。

Route::get('/users/{user}/posts/{post}', [PostController::class, 'show'])
    ->scopeBindings();

これにより、{post}{user} に属するものだけが解決対象になります。
別ユーザーのリソースへのアクセスは404になるため、認可ロジックの一部を宣言的に表現できます。

ルートグループ全体に適用することも可能です。

Route::scopeBindings()->group(function () {
    Route::get('/users/{user}/posts/{post}', [PostController::class, 'show']);
});

ソフトデリートされたモデルの解決

デフォルトでは、ソフトデリートされたモデルは解決されません。
withTrashed() をルートに付与することで解決対象に含められます。

Route::get('/posts/{post}', [PostController::class, 'show'])
    ->withTrashed();

カスタム解決ロジック(resolveRouteBinding

モデル側でバインディングロジックを完全に制御したい場合は、resolveRouteBinding をオーバーライドします。

// Post.php
public function resolveRouteBinding(mixed $value, ?string $field = null): ?Model
{
    return $this->where($field ?? $this->getRouteKeyName(), $value)
        ->where('is_published', true)
        ->firstOrFail();
}

この方法はモデルにドメインロジックを閉じ込められる一方、解決ロジックがルート定義から見えなくなるため、チームの規模や可読性のトレードオフを考慮してください。

まとめ

方法 ユースケース
暗黙的バインディング 標準的なCRUD操作
{param:column} 記法 スラッグ・UUIDなど主キー以外での解決
明示的バインディング 複雑なクエリやカスタムロジック
スコープ付きバインディング 親子関係の強制・認可の宣言的表現
resolveRouteBinding モデル側にロジックを閉じ込めたい場合

ルートモデルバインディングを適切に活用することで、コントローラはモデルの取得処理から解放され、ビジネスロジックに集中できます。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください