Ответ
В PHP исключения представлены объектами. Базовым классом для всех исключений является встроенный класс Exception или, начиная с PHP 7, интерфейс Throwable, который он реализует.
Пример базовой обработки:
try {
if ($file === null) {
throw new InvalidArgumentException('Файл не указан.');
}
$content = file_get_contents($file);
} catch (InvalidArgumentException $e) {
// Ловим конкретный тип исключения
echo 'Ошибка аргумента: ' . $e->getMessage();
log_error($e->getFile(), $e->getLine());
} catch (Exception $e) {
// Ловим все остальные исключения
echo 'Произошла общая ошибка: ' . $e->getMessage();
}
Класс Exception предоставляет методы для отладки:
getMessage()— сообщение об ошибке.getCode()— числовой код ошибки.getFile(),getLine()— место возникновения.getTrace(),getTraceAsString()— стек вызовов.
Создание пользовательского исключения:
class ConfigurationException extends RuntimeException
{
protected $configKey;
public function __construct(string $key, string $message = '', int $code = 0, Throwable $previous = null)
{
$this->configKey = $key;
parent::__construct($message ?: "Ошибка в конфигурационном ключе: {$key}", $code, $previous);
}
public function getConfigKey(): string
{
return $this->configKey;
}
}
// Использование
throw new ConfigurationException('database.host'); Ответ 18+ 🔞
Давай разберем, как в PHP с этими исключениями работать, а то там порой такой пиздец творится, что волосы дыбом встают. Представь, что исключения — это просто объекты, ну как коробки, в которые запихнули ошибку и кинули тебе в голову. Базовый класс для всей этой движухи — Exception, а с седьмой версии PHP ещё и интерфейс Throwable появился, который этот класс реализует. В общем, хуй с горы, главное — понять принцип.
Вот смотри, как это обычно выглядит на практике:
try {
if ($file === null) {
throw new InvalidArgumentException('Файл не указан.');
}
$content = file_get_contents($file);
} catch (InvalidArgumentException $e) {
// Ловим конкретный тип исключения
echo 'Ошибка аргумента: ' . $e->getMessage();
log_error($e->getFile(), $e->getLine());
} catch (Exception $e) {
// Ловим все остальные исключения
echo 'Произошла общая ошибка: ' . $e->getMessage();
}
Суть в чём: ты пытаешься выполнить код в try, и если там что-то пошло не так — выкидываешь исключение командой throw. А потом ловишь его в catch, как какого-нибудь жулика. Можно ловить конкретные типы, например, InvalidArgumentException, а можно и все подряд через общий Exception. Удобно, ёпта.
У самого объекта исключения есть куча полезных методов, чтобы понять, где и что наебнулось:
getMessage()— собственно, текст ошибки, который ты сам и написал.getCode()— какой-то числовой код, если нужен.getFile(),getLine()— файл и строка, где всё полетело к чертям. Без этого иногда вообще нихуя не понятно.getTrace(),getTraceAsString()— стек вызовов, то есть полная история, кто кого вызывал перед тем, как всё накрылось медным тазом. Для отладки — самое то.
А теперь самое интересное — можно свои собственные исключения наколдовать. Это когда стандартные тебе не подходят, и ты хочешь запихнуть в ошибку ещё какую-то свою информацию. Выглядит это примерно так:
class ConfigurationException extends RuntimeException
{
protected $configKey;
public function __construct(string $key, string $message = '', int $code = 0, Throwable $previous = null)
{
$this->configKey = $key;
parent::__construct($message ?: "Ошибка в конфигурационном ключе: {$key}", $code, $previous);
}
public function getConfigKey(): string
{
return $this->configKey;
}
}
// Использование
throw new ConfigurationException('database.host');
Создал класс ConfigurationException, который наследуется от RuntimeException. В конструктор передаёшь ключ конфига, а потом можешь его через getConfigKey() вытащить. Получается не просто «чё-то сломалось», а конкретно «сломалось вот тут, в настройке базы данных». Красота, ядрёна вошь! Теперь твоя ошибка сама расскажет, в чём дело, а не будет загадкой, как пизда с ушами. Главное — не забудь потом это исключение поймать, а то оно так и будет лететь наверх, пока скрипт не сдохнет с позором.