tohokuaikiのチラシの裏

技術的ネタとか。

LaravelのPolicyを二重にしたらダメだった

$ ./artisan --version
Laravel Framework 6.18.26

です。

Policy使ってアクセス制限

こんな感じ。

<?php
class UserController extends Controller
{
    /**
     * UserController constructor.
     */
    public function __construct()
    {
        $this->authorizeResource(User::class);
    }


    /**
     * @param Request $request
     * @return \Illuminate\Http\JsonResponse
     * @throws \Illuminate\Auth\Access\AuthorizationException
     */
    public function index(Request $request)
    {
        $this->authorize('viewAny');
        $users = User::all();
        return response()->json(['users' => $users]);
    }

そしたら、UserPolicyで

<?php
class UserPolicy
{
    use HandlesAuthorization;

    /**
     * Determine whether the user can view any models.
     *
     * @param  \App\User  $user
     * @return mixed
     */
    public function viewAny(User $user)
    {
        return true;
    }

ってしてるのにエラーが出る。 なんでUserController::index()で$this->authorize('viewAny')をわざわざ入れたかって言うのは、Controllerメソッドとの対応が https://reffect.co.jp/laravel/laravel-gate-policy-understand#Policy-3 このページの表を見ても無かったから。

あれー、って思って、実装している
laravel\framework\src\Illuminate\Foundation\Auth\Access\AuthorizesRequests.php を見てみると、

<?php
trait AuthorizesRequests
{
...
    protected function resourceAbilityMap()
    {
        return [
            'index' => 'viewAny',
            'show' => 'view',
            'create' => 'create',
            'store' => 'create',
            'edit' => 'update',
            'update' => 'update',
            'destroy' => 'delete',
        ];
    }

なー、indexとviewAnyが対応してるやん…

2回やってもture返すならいいんじゃないかと思ったけど、2回やるとダメなんね。

ということで、 $this->authorize('viewAny'); を取って解決。