bool каже лише «можна» чи «ні». Response дає ще й пояснення та керує тим, що побачить користувач.
Повідомлення про причину:
public function update(User $user, Post $post): Response
{
if ($post->is_locked) {
return Response::deny('Статтю заблоковано модератором.');
}
return $user->id === $post->user_id
? Response::allow()
: Response::deny('Ви не автор цієї статті.');
}
Коли Gate::authorize('update', $post) кидає AuthorizationException, це повідомлення потрапляє у відповідь 403. Без винятку його можна прочитати через Gate::inspect() - наприклад, щоб показати підказку біля неактивної кнопки.
404 замість 403:
return $user->id === $invoice->user_id
? Response::allow()
: Response::denyAsNotFound();
403 підтверджує, що рахунок з таким номером існує. Для приватних ресурсів 404 нічого не розкриває - стороння людина не відрізнить чужий рахунок від неіснуючого. Є й denyWithStatus() для довільного коду.
Коли досить bool: коли причина очевидна й однакова - «не власник». Response окупається, де причин кілька або сам факт існування ресурсу приватний.