I have blog posts that only the author or an admin can edit. I see Gate::define, policies, can() and @can in the docs. How do I choose and how do I wire it up so the controller returns 403 automatically?
#laravel#authorization#policies
DEV3 Developer Forum
Every post is reviewed first. Usually reviewed within 24 hours.
I have blog posts that only the author or an admin can edit. I see Gate::define, policies, can() and @can in the docs. How do I choose and how do I wire it up so the controller returns 403 automatically?
#laravel#authorization#policies
Use policies when the check is about a specific model (post, invoice, project). Use gates for model-less checks such as "can view the admin dashboard".
Policy
php artisan make:policy PostPolicy --model=Post
class PostPolicy
{
public function before(User $user): ?bool
{
return $user->is_admin ? true : null; // null falls through to the method
}
public function update(User $user, Post $post): bool
{
return $user->id === $post->user_id;
}
}
Laravel auto-discovers PostPolicy for Post in app/Policies.
Use it in the controller
public function update(Request $request, Post $post)
{
$this->authorize('update', $post); // or Gate::authorize(...)
// ...
}
A denial throws AuthorizationException, rendered as 403. In Laravel 12 the base controller does not include AuthorizesRequests any more; use Gate::authorize('update', $post) or add the trait. Route-level alternative:
Route::put('/posts/{post}', [PostController::class, 'update'])->can('update', 'post');
Gate
Gate::define('view-admin', fn (User $user) => $user->is_admin);
In Blade and code
@can('update', $post) <a href="...">Edit</a> @endcan
if ($request->user()->cannot('update', $post)) { abort(403); }
Pitfalls
before() returning false denies everything. Return true or null only for an admin bypass.?User $user in the policy method to allow them.