Ответ
Да, создание собственных классов исключений — это лучшая практика для точной обработки ошибок, специфичных для бизнес-логики приложения.
Пример создания и использования:
// Пользовательское исключение для ошибок валидации
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 упавшего заказа. Потом из исключения это всё вытащишь и используешь. Не надо изобретать велосипед с глобальными переменными или ещё какой хуйнёй.
Короче, не ленись, чувак. Потрать пятнадцать минут, чтобы написать класс исключения, и сэкономишь себе и другим овердохуища нервов при отладке.