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

Як спроєктувати власні винятки для бібліотеки чи модуля?

Мета - щоб код, який використовує модуль, міг зловити саме те, що вміє обробити, і нічого зайвого.

Типова структура:

interface PaymentException extends Throwable {}

final class CardDeclined extends RuntimeException implements PaymentException
{
    public static function forReason(string $reason): self
    {
        return new self("Картку відхилено: {$reason}");
    }
}

final class GatewayUnavailable extends RuntimeException implements PaymentException {}

Принципи:

  • Маркерний інтерфейс модуля (PaymentException) дозволяє зловити все з модуля одним catch, не прив'язуючись до ієрархії класів.
  • Успадкування від SPL-винятків (RuntimeException, InvalidArgumentException, LogicException) зберігає зміст: LogicException - помилка програміста, RuntimeException - обставини під час виконання.
  • Іменовані конструктори (forReason()) тримають формулювання повідомлень в одному місці.
  • Контекст як властивості, а не лише в тексті: $e->orderId можна записати в лог чи показати користувачу без розбору рядка.
  • Ланцюжок причин: загортаючи чужий виняток, передавайте його як previous - інакше в логах загубиться справжня причина.

Чого уникати: винятків для звичайного керування потоком (користувач не знайдений - часто це null, а не виняток) і одного «універсального» AppException на все.

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

Перевір себе

20 випадкових питань за спробу, після завершення - розбір кожної помилки

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