Route Model Binding はリソース解決を認可から分離する
URL の {id} を受け取ったコントローラが毎回 find(id) する代わりに、ルーティング層が ID からドメインオブジェクトを解決してコントローラ引数へ渡す仕組みが Route Model Binding / Entity Value Resolver である。
Laravel では /users/{user} と User $user を対応させると Eloquent モデルが自動解決される。Symfony でも EntityValueResolver が /product/{id} から Product $product を取得し、存在しなければ 404 にする。これは リソースベース認可では認可より先にリソース解決が必要 の「まずリソースを解決する」という前半をフレームワークへ移す仕組みと見なせる。
重要なのは、解決されたモデルはまだ認可済みではないという点である。Laravel では can:update,post middleware や Policy が、Route Model Binding 済みの Post を受け取って認可する。Symfony では #[IsGranted('edit', 'post')] がコントローラ引数の Post を subject として Voter に渡す。
つまり両者は、概念的には次の二段構えになっている。
route parameter -> resource resolver -> Post
-> policy / voter -> controller
この分離の利点は、404 と 403 の責務、オブジェクト解決、認可ロジックをそれぞれ独立して再利用できることにある。一方でコントローラの型だけを見ても、その Post が認可済みかどうかは分からない。ここをさらに型や依存関係のグラフで表現する方向が 認可済みリソースをハンドラ入力にすると前提を構造化できる である。