Laravelでは、Policyを使って、モデルごとに対してアクセスや動作・表示制限をかけられます。
リソースコントローラーにPolicyを適用させる場合、CRUDメソッドに簡単に適用させられます。
便利ながら、トラップもあり。
トラップを避けてリソースコントローラーにPOLICYを適用させる方法を解説していきますね。
LaravelのPolicyを効率的にCRUDメソッドに適用させる方法
今回は、PostモデルのためのPolicyを作ります。
これによって、投稿(Post)を編集したり、削除したりできるのは作成者本人だけ、という制限をかけます。
手順は次のとおり。
- Postモデルとコントローラーを作成
- Policyファイルを作成
- Policyファイルを編集
- PostコントローラーにPolicy適用
- トラップについて
公式マニュアルはこちら。
Postモデルとコントローラーを作成
Postモデルとマイグレーションファイル、リソースコントローラーを作成します。
下記のようにコマンドを入れると、一度で、この3つのファイルを作成できます。
| 1 | php artisan make:model Post -m -c --resource | 
各メソッドへのコードの記入方法は、ここでは省略させてください。
なお、リソースコントローラーにはCRUD処理に対応したメソッド名が既に入っています。

「そもそもCRUDってなに?」と思ったら、こちらから読んでくださいね。
Policyファイルを作成
下記コマンドで、PostモデルのPolicy用ファイルを作成します。
| 1 | php artisan make:policy PostPolicy --model=Post | 
作成後、app/Providersの中の AuthServiceProvider.phpファイルに登録しておきます。
| 1 2 3 |     protected $policies = [         App\Models\Post::class=>App\Policies\PostPolicy::class,     ]; | 
Policyファイルを編集
PostPolicyファイルを開きます。
最初から7つのメソッドが入っていますが、そのうち5つは、リソースコントローラーのメソッドに対応しています。
対応表は次のとおりです。
| リソースコントローラーメソッド | Policyメソッド | 
| index | viewAny | 
| show | view | 
| create | create | 
| store | create | 
| edit | update | 
| update | update | 
| destroy | delete | 
コントローラーに対応したPolicyメソッドに、制限をいれていきます。
作成した本人だけに許可が編集OKとするなら、次のようにいれます。
| 1 2 3 4 |     public function update(User $user, Post $post)     {         return $user->id==$post->user->id;     } | 
本人しか見れない、削除できない、とするなら、同じ記述をviewやdeleteメソッドにも入れておくと良いでしょう。
| 1 2 3 4 |     public function view(User $user, Post $post)     {         return $user->id==$post->user->id;     } | 
| 1 2 3 4 |     public function delete(User $user, Post $post)     {         return $user->id==$post->user->id;     } | 
これでPolicy編集終わり。
PostコントローラーにPolicy適用
コントローラーに、今作成したPolicyを適用させます。
といっても、下記を入れるだけ。
| 1 2 3 4 |     public function __construct()     {         $this->authorizeResource(Post::class, 'post');     } | 
では早速、テストしてみましょう。
トラップについて
おそらく、うまくいかない方が多いと思います^^;
実は、リソースコントローラー対応Policyには、トラップがあります。
わたしが気付いたのは、下記の2か所。
トラップ① 制限がないところにもPolicyを記述せねばならない
たとえば 【create】メソッドは、制限なく、だれでもできるようにしたいとします。
ところが、こういった部分にもPolicyを入れておく必要があります。
そうしないと、このように403エラーになります。

制限がない場合には、PostPolicyのcreateメソッドに、次のように return true をいれておきましょう。
| 1 2 3 4 |     public function create(User $user)     {         return true;     } | 
トラップ② デフォルトの引数を変えると動作しない、こともある。
ふたつめのトラップは、コントローラーの中の引数を変えると、動作しないことがあるという点。
たとえば、deleteメソッドはデフォルトでは次のようになっています。
| 1 | public function destroy(Post $post) | 
ですが、わたしは次のようにしていました。
| 1 | public function destroy(Request $request, Post $post) | 
すると、またしても 403 unauthorizedエラーが。
デフォルトと変更した箇所がある場合には、動作しない場合があるかもしれません。
そんな場合には、一度、デフォルトに戻してチェックしてみてください。

ほんと、融通利かない!と正直思いましたが。
さいごに
今回は、モデルとリソースコントローラーに紐づけたPolicyの使い方を解説しました。
たしかに記述量が少なくて便利ですが、融通が利かない部分もあり。
不便だと感じたら、一か所ずついれておくほうが良いかと思います。
その方法は、こちらの記事をご覧ください。
他にも関連記事で制限のかけかたを色々解説しているので、あなたの状況にあったものを選んでくださいね。
 
  
  
  
  


