Можно ли создавать пользовательские исключения в PHP?

Ответ

Да, создание собственных классов исключений — это лучшая практика для точной обработки ошибок, специфичных для бизнес-логики приложения.

Пример создания и использования:

// Пользовательское исключение для ошибок валидации
class ValidationException extends InvalidArgumentException {
    private array $errors;

    public function __construct(string $message, array $errors = [], int $code = 0, ?Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
        $this->errors = $errors;
    }

    public function getErrors(): array {
        return $this->errors;
    }
}

// Использование в сервисе
class UserRegistrationService {
    public function register(array $data): void {
        $errors = $this->validate($data);
        if (!empty($errors)) {
            throw new ValidationException('Ошибка валидации данных пользователя', $errors);
        }
        // ... логика регистрации
    }
}

// Точечная обработка
try {
    $service->register(['email' => 'invalid']);
} catch (ValidationException $e) {
    echo $e->getMessage();
    foreach ($e->getErrors() as $error) {
        echo "- $errorn";
    }
}

Преимущества:

  • Семантика: Исключения отражают конкретную проблему (ValidationException, PaymentFailedException).
  • Точный перехват: Можно ловить только нужные типы исключений, не обрабатывая все через общий Exception.
  • Дополнительные данные: Класс исключения может содержать специфичную для ошибки информацию (как $errors в примере выше).

Ответ 18+ 🔞

А, ну это ж классика, про которую все вроде знают, но на деле нихуя не делают. Создавать свои классы для ошибок — это как не ебать мозг себе и всем, кто будет твой код читать потом. Представь, у тебя в коде просто throw new Exception('Всё сломалось'). И что? Чё сломалось-то? Почему? Куда бежать? Пиздец, волнение ебать, а понять нихуя.

Вот смотри, как надо, чтобы не было потом "сам от себя охуел", глядя на логи.

// Вот это наше, родное, для случаев, когда пользователь насрал в данные
class ValidationException extends InvalidArgumentException {
    private array $errors; // Сюда сложим все косяки

    public function __construct(string $message, array $errors = [], int $code = 0, ?Throwable $previous = null) {
        parent::__construct($message, $code, $previous);
        $this->errors = $errors; // Припрятали ошибки внутрь
    }

    public function getErrors(): array {
        return $this->errors; // А вот и геттер, чтобы достать
    }
}

// Допустим, у нас сервис регистрации. Без него нихуя.
class UserRegistrationService {
    public function register(array $data): void {
        $errors = $this->validate($data); // Проверили
        if (!empty($errors)) {
            // Бросаем НЕ абы что, а нашу конкретную дуру
            throw new ValidationException('Ошибка валидации данных пользователя', $errors);
        }
        // ... дальше уже логика, если всё чисто
    }
}

// И вот магия! Ловим не всё подряд, а именно то, что нужно.
try {
    $service->register(['email' => 'invalid']); // Очевидно же, что кринж
} catch (ValidationException $e) { // Поймали именно её, а не какую-то левую
    echo $e->getMessage(); // Вывели общее сообщение
    // А тут достали все косяки по полочкам! Удобно же, ёпта!
    foreach ($e->getErrors() as $error) {
        echo "- $errorn";
    }
}

И в чём, собственно, профит, спросишь ты? А вот, держи:

  • Ясность, блять: По названию исключения сразу ясно, что случилось. Не просто Exception, а ValidationException или, там, PaymentFailedException. Сразу понятно, в каком месте системы ебучка.
  • Точечный отлов: Можешь ловить только то, что можешь обработать. ValidationException — показать юзеру, DatabaseConnectionException — переподключиться и залогировать, а OutOfBeerException — срочно ехать в магазин. Всё по делу, без этого "накрылся медным тазом" на ровном месте.
  • Дополнительная инфо: Внутрь своей ошибки можешь запихнуть что угодно: массив полей-косяков, код ошибки от платёжки, ID упавшего заказа. Потом из исключения это всё вытащишь и используешь. Не надо изобретать велосипед с глобальными переменными или ещё какой хуйнёй.

Короче, не ленись, чувак. Потрать пятнадцать минут, чтобы написать класс исключения, и сэкономишь себе и другим овердохуища нервов при отладке.