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の使い方を解説しました。
たしかに記述量が少なくて便利ですが、融通が利かない部分もあり。
不便だと感じたら、一か所ずついれておくほうが良いかと思います。
その方法は、こちらの記事をご覧ください。
他にも関連記事で制限のかけかたを色々解説しているので、あなたの状況にあったものを選んでくださいね。