patternphplaravelTip
Policies and Gates: When to Use Which
Viewed 0 times
policygateauthorizationauthorizecanbeforeAuthServiceProviderpermissions
Error Messages
Problem
Authorization checks are written ad-hoc in controllers using custom if-statements. Permissions for the same resource are duplicated across multiple places and are hard to audit.
Solution
Use Gates for simple, non-model-specific checks: Gate::define('view-dashboard', fn(User $u) => $u->isAdmin()). Use Policies for model-specific authorization: php artisan make:policy PostPolicy --model=Post. Register policies in AuthServiceProvider. Check via $this->authorize('update', $post) in controllers or @can in Blade.
Why
Policies provide a structured, testable location for authorization logic tied to a model. Gates are closures suitable for actions not tied to a specific model. Both integrate with @can and middleware.
Gotchas
- Laravel auto-discovers policies by convention if model and policy are in standard locations
- The before() method in a policy is checked first and can short-circuit all other checks (useful for admins)
- Gate::before() and Gate::after() affect ALL gate checks globally—use with care
- Using ->authorize() in a controller throws AuthorizationException (403), not a redirect
Code Snippets
Policy with before() super-admin bypass
class PostPolicy
{
public function before(User $user): ?bool
{
return $user->isSuperAdmin() ? true : null;
}
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}Revisions (0)
No revisions yet.