In a controller, call Gate::authorize(), which throws on denial, or test $request->user()->cannot('update', $review) to respond another way. $this->authorize() still works, but only with the AuthorizesRequests trait, which the empty base Controller of a Laravel 13 2,157 skeleton lacks. To refuse a request before the controller runs, attach the can middleware with ->can() or can:ability,parameter:
use AuthorizesRequests; // only needed for $this->authorize()
Gate::authorize('view', $review); // in show()
$this->authorize('update', $review); // in update(): the same check, trait style
// routes/web.php, inside Route::middleware('auth')->group()
Route::delete('/reviews/{review}', [ReviewController::class, 'destroy'])
->can('delete', 'review');
Route::get('/dashboard', fn () => ['page' => 'dashboard'])->middleware('can:view-dashboard');$ try -b ann.jar -X DELETE $B/reviews/2 403 {"message":"This action is unauthorized."} $ try -b sam.jar -X DELETE $B/reviews/2 200 {"deleted":2} $ try $B/dashboard 401 {"message":"Unauthenticated."} |
| The ->can() and can: routes for a customer, staff and a guest |
The second can argument names a route parameter, so the policy receives the bound Review; for model-less abilities pass the class, ->can('create', Review::class). A plain false gives the generic message, so return Response::deny() where the user deserves a reason. The guest got 401 because auth runs before can.