Коли під час запиту виникає виняток і ніхто його не перехопив, Laravel передає його обробнику винятків. Обробник робить дві незалежні речі:
| Крок | Що відбувається | Для кого |
|---|---|---|
| report (звітування) | запис у лог, відправка в Sentry, Flare, Bugsnag | для розробників |
| render (рендеринг) | перетворення винятку на HTTP-відповідь | для користувача |
виняток → report: laravel.log, Sentry
→ render: сторінка 500, JSON {"message": "..."}, редірект з помилками валідації
Чому це розділено: те, що бачить користувач, і те, що бачить розробник, мають бути різними. Користувачу - зрозуміле повідомлення без деталей, розробнику - повний стек викликів, контекст запиту, користувач.
Як Laravel рендерить різні винятки:
ValidationException- редірект назад з помилками й старим введенням, або 422 з JSON для API;AuthenticationException- редірект на сторінку входу чи 401;AuthorizationException- 403;ModelNotFoundException(відfindOrFail) - 404;HttpException(відabort(404)) - відповідний код;- будь-що інше - 500.
Деякі винятки взагалі не звітуються: валідація, 404, помилки автентифікації - це очікувані ситуації, а не баги. Інакше лог заповнився б шумом.
JSON чи HTML: якщо запит очікує JSON (заголовок Accept: application/json), Laravel повертає помилку у форматі JSON.
APP_DEBUG:
true- сторінка помилки зі стеком викликів, кодом і змінними - лише для локальної розробки;false- загальна сторінка «Server Error» без деталей. На продакшені тільки так.
Налаштовується все в bootstrap/app.php:
->withExceptions(function (Exceptions $exceptions): void {
$exceptions->report(function (PaymentFailed $e) {
// власне звітування
});
$exceptions->render(function (PaymentFailed $e, Request $request) {
return response()->view('errors.payment', status: 402);
});
})