はじめに
Laravelでダイアリー共有アプリを制作している中で、初心者ながら学んだことをアウトプットしていきたいと思います。初心者🔰につき、至らない点が多々あるかもしれませんが、何卒。
本記事の動作環境
- Laravel 12.25.0
- Docker + Laravel Sailを使用
- macOS (M1)
やりたいこと
ユーザーのフォロー機能に続き、次にブロック機能を実装中。
今回、
「ブロックされているユーザーは、ブロックしたユーザーのプロフィール画面を見ることができない」
をLaravelの Policy(ポリシー) を使って実現したい。
試したこと
app/Policies/UserPolicy.phpを作り、プロフィール表示を判断するviewメソッドを書きます。
(コマンドの頭に./vendor/bin/sailがつきますが、省略しています)
php artisan make:policy UserPolicy
public function view(User $currentUser, User $profileUser)
{
// プロフィールの持ち主が、見ようとしているユーザーをブロックしているか?
return !$profileUser->blocks()->where('users.id', $currentUser->id)->exists();
}
-
$currentUser...今ログインしているユーザー -
$profileUser...プロフィールの持ち主
なお、blocks()は、Userモデルに定義した「ブロックしているユーザーを取得するためのリレーション」 です。
続いて、コントローラ側でポリシーを適用します。
public function show(User $user)
{
Gate::authorize('view', $user);
// 省略
return view('user_profile.show', compact('user'));
}
これで実際にプロフィール画面にアクセスしたところ、ブロックされていないユーザーも含め、すべてのユーザーが 403 になり、見られなくなりました。
原因
原因はシンプルで、
Userモデル とUserPolicy を
AppServiceProviderで紐付けていませんでした。
一方で、フォロー機能を実装した際に登録した、UserモデルとUserFollowPolicyの対応づけがありました。
public function boot(): void
{
// Policyの登録。UserモデルとUserFollowPolicyの対応づけ。
Gate::policy(User::class, UserFollowPolicy::class);
}
userモデルに紐づいたPolicyがUserFollowPolicyだけで、そこにviewメソッドがないため、全員に403が返ってきていたようです。
解決策
AppServiceProviderにUserモデルとUserPolicyの対応づけを行いました。
public function boot(): void
{
// Policyの登録。UserモデルとUserPolicyの対応づけ。
Gate::policy(User::class, UserPolicy::class);
}
また、同じUserモデルに2つのPolicyを登録することになるため、UserFollowPolicyの紐付けは削除し、中にあったfollow/unfollowメソッドはUserPolicyに統合しました。
これで、
「ブロックされているユーザーは、ブロックしたユーザーのプロフィール画面を見ることができない」
を実現することができました。
おわりに
Policyの登録を調べると概ねAuthServiceProviderに登録するように書いてあります。
しかし、ワタシの環境Laravel12では、デフォルトでAuthServiceProviderが存在せず、Policyの登録は、AppServiceProviderに登録するようです。
公式ドキュメントでも、「ポリシーの手作業による登録」として、以下のような記述があります。
Gateファサードを使用すると、アプリケーションの AppServiceProviderのbootメソッド内で、ポリシーと対応するモデルを手作業で登録できます。
モデル名とポリシーが命名規則に従っていれば、Laravelが自動的に紐付けを行うので、手作業で登録する必要はありません。
今回のようにフォロー・ブロック機能では、対象モデルがUserのため、Policyメソッドの引数がUser、Userになるので、ややこしかったです。
同じようにつまづく方の参考になれば幸いです。
参考
記事の書き方は@Sicut_studyさんの以下を参考にさせていただきました。