概要
ルートモデルバインディングとは、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 または AppServiceProvider の boot() メソッドでバインディングを明示的に定義します。
カスタムクエリや複雑なロジックが必要な場合に有効です。
// 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 |
モデル側にロジックを閉じ込めたい場合 |
ルートモデルバインディングを適切に活用することで、コントローラはモデルの取得処理から解放され、ビジネスロジックに集中できます。