tohokuaikiのチラシの裏

技術的ネタとか。

LaravelでPolicyを追加する時に、ModelがInjectionしてくれなくて困った件

この辺りを読んでて… readouble.com

route/api.php

<?php
    Route::post('user/confirm', 'UserController@confirm')->name('user.create.confirm')->middleware('can:confirm,App\User');
    Route::post('user/{user}/confirm', 'UserController@confirm')->name('user.update.confirm')->middleware('can:confirm,App\User');

って書いて、UserPolicyのcnofirmメソッドに

<?php
    public function confirm(User $user, User $model = null)
    {

って書いたけど、$modelにObjectあきよらん…って思ってたけど、

createのようなアクションではモデルインスタンスを必要としません。このようなケースでは、ミドルウェアへクラス名を渡してください。クラス名はアクションを認可するときに、どのポリシーを使用するかの判断に使われます。

とあって、->middleware()の第二引数(正確には第一引数のカンマ区切り2個目)にクラスを書くのはmodelが不要なときだった…

$modelが必要な場合は

canミドルウェアへ2つの引数を渡しています。最初の引数は認可したいアクションの名前です。2つ目はポリシーメソッドに渡したいルートパラメータです。

とあるように、Routeで{user}としたものが入るので↑のRouteの記述は

<?php
    Route::post('user/confirm', 'UserController@confirm')->name('user.create.confirm')->middleware('can:confirm,App\User');
    Route::post('user/{user}/confirm', 'UserController@confirm')->name('user.update.confirm')->middleware('can:confirm,user');

とやるのが正解。