Исключения — это новые и важные компоненты РНР5, представляющие универсальный механизм расширяемой, удобной для обслуживания и объектно-ориентированной обработки ошибок.
Концепция обработки ошибок
Основная идея обработки ошибок состоит в выполнении кода внутри так называемого блока try
. Этот блок представляет собой раздел кода следующего вида:
try
{
//здесь находится необходимый код
}
В случае возникновения непредвиденных ситуаций внутри блока try
можно выполнить так называемую генерацию исключения. В РНР исключения нужно генерировать вручную. Это выполняется следующим образом:
throw new Exception ('сообщение ', код);
Ключевое слово throw
включает механизм обработки исключения. Приведенный фрагмент скорее представляет собой конструкцию языка, а не функцию, но ему необходимо передать значение. Эта конструкция ожидает получения объекта. В простейшем случае ее можно использовать для создания экземпляра встроенного класса Exception
, как и было сделано в приведенном примере.
Конструктор этого класса принимает два параметра: сообщение и код. Они служат для представления сообщения об ошибке и номера ошибки. Оба эти параметра необязательны.
И наконец, за блоком try должен следовать как минимум один блок catch
, который выглядит подобно показанному ниже:
catch (указание_типа исключения)
{
// обработка исключения
}
Объект, передаваемый в блок catch (и перехватываемый им), является тем, который передается (и генерируется) оператором throw
, генерирующим исключение. Исключение может быть любого типа, однако удобнее всего использовать либо класс Еxception
, либо экземпляры собственных пользовательских исключений, унаследованных от класса Еxception
.
В случае возникновения исключения код РНР ищет соответствующий блок catch
. При наличии более одного блока catch
передаваемые в них объекты должны иметь различные типы, чтобы РНР мог определить, какой именно блок catch соответствует конкретному случаю.
Еще один заслуживающий внимания момент связан с возможностью генерирования дополнительных исключений внутри блока catch
.
Рассмотрим простой пример обработки исключений:
<?php
try
{
throw new Exception ('Возникла очень серьезная ошибка', 42);
}
catch (Exception $e)
{
echo 'Исключение '. $e -> getCode(). ': '. $e -> getMessage() . ' в ' . $e -> getFile(). ', строка '. $e ->getLine(). '<br>';
}
?>
Результат выполнения кода показан ниже на рисунке.
Из листинга видно, что мы воспользовались несколькими методами класса Exception
, которые будут рассмотрены позже. В приведенном примере кода было сгенерировано исключение класса Exception
. Методы этого встроенного класса можно использовать в блоке catch
для вывода полезного сообщения об ошибке.
Класс Exception
PHP5 поставляется со встроенным классом Exception
. Как уже упоминалось, конструктор этого класса принимает два параметра: сообщение об ошибке и номер ошибки.
Кроме конструктора, этот класс содержит следующие встроенные методы:
getCode()
— возвращает код, переданный конструктору;getVessage()
— возвращает сообщение, переданное конструктору;getFile()
— возвращает полный путь файла кода, в котором возникло исключение;getLine()
— возвращает количество строк в файле кода, в котором возникло исключение;getTrace()
— возвращает массив, содержащий информацию отслеживания места возникновения исключения;getTraceAsString()
— возвращает ту же информацию, что и методgetTrace
, но сформированную в виде строки;__toString()
— позволяет упростить вывод с помощью echo объекта Exception
, предоставляя всю информацию, полученную из перечисленных методов.
Как видите, в коде листинга были использованы четыре из этих методов. Эту ж еинформацию (плюс информацию отслеживания) можно было бы получить с помощью оператора:
echo $e;
Информация отслеживания указывает, какие функции выполнялись в момент возникновения исключения.
Исключения, определяемые пользователем
Вместо создания и передачи экземпляра базового класса Exception
можно передавать любой другой объект. В большинстве случаев вы будете расширять класс Exception
для создания своих собственных классов и исключений.
Конструкция throw
позволяет передавать любые другие объекты. иногда такая потребность может возникнуть при наличии проблем, связанных с каким-то конкретным объектом, и необходимости его передачи в целях отладки.
Как уже говорилось, в большинстве случаев приходится расширять базовый класс Exception
. В руководстве по РНР показан код, который демонстрирует основу класса Exception
.
Класс Exception — компоненты класса, которые можно наследовать
<?php
class Exception {
function __construct (string $message = NULL, int $code = 0)
{
if (func_num_args())
{
$this -> message = $message;
}
$this -> code = $code;
$this -> file = __FILE__;//из конструкции throw
$this -> line = __LINE__;//из конструкции throw
$this -> trace = debug_backtrace();
$this -> string = StringFormat
($this);}
protected $message = 'Unknown exception';//сообщение исключения
protected $code = 0; //определяемый пользователем код исключений
protected $file; // исходное имя файла
protected $line; //исходная строка исключения
private $trace; //информация отслеживания
private $string; //только для внутреннего пользования!!
final function getMessage()
{
return $this -> message;
}
final function getCode()
{
return $this -> code;
}
final function getFile()
{
return $this -> file;
}
final function getTrace()
{
return $this -> trace;
}
final function getTraceAsString()
{
return self::TraceFormat($this);
}
function __toString()
{
return $this -> string;
}
static private function StringFormat(Exception $exception)
{
//... недоступная в РНР-сценариях функция,
//которая возвращает всю необходимую информацию в виде строки
}
static private function TraceFormat(Exception $exception)
{
// ... недоступная в РНР-сценариях функция,
//которая возвращает всю информацию отслеживания в виде строки
}
}
?>
Основная причина, по которой было приведено определение класса, состоит в том, что большинство общедоступных методов являются финальными: то есть, их нельзя перекрыть. Можно создать собственный субкласс Exceptions
, но нельзя менять поведение базовых методов. Вместе с тем, можно перекрывать функцию __toString()
, чтобы изменить способ отображения исключения. Можно также добавлять собственные методы.
Пример определенного пользователем класса Exception user_defined_exception.php
<?php
class myException extends Exception
{
function __toString()
{
return '<table border><tr><td><strong>Исключение '. $this -> getCode(). '</strong>: '.$this -> getMessage(). '<br>'.'в '
.$this-> getFile(). ', строка '. $this-> getLine()
.'</td></tr></table><br>';
}
}
try
{
throw new myException('Произошла очень серьезная ошибка ', 42);
}
catch (myException $m)
{
echo $m;
}
?>
Результат выполнения кода показан на рисунке.
В этом коде объявляется новый класс исключения с именем myException
, расширяющий класс Exception
. Различие между этим классом и классом Exception связано с заменой метода __toString()
для обеспечения более "изящного" вывода сообщения об исключении.
Приведенный пример очень прост, Далее мы рассмотрим способы создания различных исключений, связанных с различными категориями ошибок.
Комментарии(0)
Для добавления комментариев надо войти в систему и авторизоватьсяКомментирование статей доступно только для зарегистрированных пользователей:Зарегистрироваться