Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Як створити власний виняток з методами report() і render()?

Замість реєструвати колбеки в bootstrap/app.php можна описати поведінку прямо в класі винятку - методами report() і render(). Обробник Laravel викличе їх сам.

namespace App\Exceptions;

use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

final class InsufficientBalanceException extends Exception
{
    public function __construct(
        public readonly int $required,
        public readonly int $available,
    ) {
        parent::__construct('Недостатньо коштів на балансі.');
    }

    public function report(): bool
    {
        // очікувана бізнес-ситуація, звітувати не потрібно
        return true;
    }

    public function render(Request $request): Response|JsonResponse
    {
        if ($request->expectsJson()) {
            return response()->json([
                'message' => $this->getMessage(),
                'required' => $this->required,
                'available' => $this->available,
            ], 422);
        }

        return back()->withErrors(['balance' => $this->getMessage()]);
    }
}

Як працюють значення, що повертаються:

Метод Повертає Результат
report() false стандартне логування виконується
report() true чи нічого (void) виняток вважається обробленим, стандартного логування немає
render() відповідь її отримає користувач
render() false стандартний рендеринг Laravel

Навіщо власні винятки:

  • доменна мова: InsufficientBalanceException у коді й логах зрозуміліше, ніж RuntimeException('balance');
  • дані в полях: скільки потрібно, скільки є - а не розбір тексту повідомлення;
  • точкові catch: викликаючий код ловить саме цей випадок, а несподівані помилки летять далі;
  • одне місце для того, як ця ситуація виглядає для користувача.

Коли краще колбеки в bootstrap/app.php: для чужих винятків (з пакетів чи фреймворку), до класу яких немає доступу, і для спільної політики - наприклад, усі помилки API в одному форматі.

Порада щодо ієрархії: базовий виняток модуля (BillingException) і конкретні нащадки - тоді можна зловити все, що стосується модуля, одним catch, а звітування налаштувати для базового класу.

Докладніше в документації: Помилки: винятки з власним рендерингом

Схожі питання