PHP Обработка исключений


Исключения используются для изменения нормального потока выполнения скрипта при возникновении определенной ошибки.


Что такое исключение

PHP 5 предоставляет новый объектно-ориентированный метод обработки ошибок.

Обработка исключений используется для изменения нормального потока выполнения скрипта при возникновении определенного состояния ошибки (исключения). Это состояние называется исключением.

При возникновении исключения обычно происходит следующее:

  • Текущее состояние кода сохраняется
  • Выполнение кода переключается на предопределённую (пользовательскую) функцию-обработчик исключений
  • В зависимости от ситуации обработчик может возобновить выполнение кода с сохранённого состояния кода, завершить выполнение скрипта или продолжить выполнение скрипта с другого места в коде

Мы покажем различные методы обработки ошибок:

  • Базовое использование исключений
  • Создание пользовательского обработчика исключений
  • Множественные исключения
  • Повторный выброс исключений
  • Установка обработчика исключений верхнего уровня

Примечание:Исключения следует использовать только в ситуациях ошибок и не следует использовать для перехода в другое место кода в определённой точке.


Базовое использование исключений

Когда выбрасывается исключение, код после него не будет продолжать выполняться, и PHP попытается найти соответствующий блок «catch».

Если исключение не перехвачено и для соответствующей обработки не используется set_exception_handler(), то возникнет серьёзная ошибка (фатальная ошибка), и будет выведено сообщение об ошибке «Uncaught Exception».

Давайте попробуем вызвать исключение, не перехватывая его:

<?php //Создайте функцию с обработкой исключений function checkNum($number) { if($number>1) { throw new Exception("Значение должно быть 1 или меньше"); } return true; } //Вызвать исключение checkNum(2); ?>

Приведённый выше код вызовет ошибку, подобную этой:

Fatal error: Uncaught exception 'Exception' with message 'Value must be 1 or below' in /www/example/test/test.php:7 Stack trace: #0 /www/example/test/test.php(13): checkNum(2) #1 {main} thrown in /www/example/test/test.php on line 7

Try, throw и catch

Чтобы избежать ошибки, появившейся в примере выше, нам нужно создать подходящий код для обработки исключений.

Подходящий код обработки исключений должен включать:

  1. Try - Функция, использующая исключение, должна находиться внутри блока "try". Если исключение не вызвано, код продолжит выполнение как обычно. Но если исключение вызвано, выбрасывается исключение.
  2. Throw - указывает, как вызвать исключение. Каждый "throw" должен соответствовать как минимум одному "catch".
  3. Catch — блок "catch" перехватывает исключение и создаёт объект, содержащий информацию об исключении.

Давайте вызовем исключение:

<?php //Создайте функцию с обработкой исключений function checkNum($number) { if($number>1) { throw new Exception("Значение переменной должно быть меньше или равно 1"); } return true; } //Вызвать исключение в блоке try try { checkNum(2); //Если исключение выброшено, следующий текст не будет выведен echo 'Если это содержимое выводится, это означает, что переменная $number'; } //Перехватить исключение catch(Exception $e) { echo 'Сообщение: ' .$e->getMessage(); } ?>

Приведённый выше код вызовет ошибку, подобную этой:

Message: 变量值必须小于等于 1

Пояснение к примеру:

Код выше выбросил исключение и перехватил его:

  1. Создайте функцию checkNum(). Она проверяет, больше ли число 1. Если да, она выбрасывает исключение.
  2. Вызовите функцию checkNum() в блоке "try".
  3. В функции checkNum() выбрасывается исключение.
  4. Блок "catch" получает исключение и создаёт объект, содержащий информацию об исключении ($e).
  5. Вызвав $e->getMessage() для этого объекта исключения, выведите сообщение об ошибке из этого исключения.

Однако, чтобы следовать принципу «каждый throw должен соответствовать catch», можно установить обработчик исключений верхнего уровня для обработки пропущенных ошибок.


Создание пользовательского класса исключений

Создание пользовательского обработчика исключений очень просто. Мы просто создаём специальный класс, функции которого могут вызываться при возникновении исключения в PHP. Этот класс должен быть расширением класса исключений.

Этот пользовательский класс customException наследует все свойства класса исключений PHP, и вы можете добавить в него пользовательские функции.

Давайте начнём создавать класс customException:

<?php class customException extends Exception { public function errorMessage() { //Сообщение об ошибке $errorMsg = 'Номер строки с ошибкой'.$this->getLine().' в '.$this->getFile() .': <b>'.$this->getMessage().'</b> не является допустимым адресом E-Mail'; return $errorMsg; } } $email = "[email protected]"; try { //Проверить e-mail if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //Если это недействительный адрес e-mail, выбросить исключение throw new customException($email); } } catch (customException $e) { //отобразить пользовательское сообщение echo $e->errorMessage(); } ?>

Этот новый класс — это копия старого класса исключений вместе с функцией errorMessage(). Поскольку он является копией старого класса, он наследует свойства и методы старого класса, и мы можем использовать методы класса исключений, такие как getLine(), getFile() и getMessage().

Пояснение к примеру:

Приведённый выше код выбросил исключение и перехватил его с помощью пользовательского класса исключений:

  1. Класс customException() создан как расширение старого класса исключений. Таким образом, он наследует все свойства и методы старого класса исключений.
  2. Создайте функцию errorMessage(). Если адрес e-mail недействителен, эта функция возвращает сообщение об ошибке.
  3. Присвойте переменной $email строку с недействительным адресом e-mail.
  4. Выполняется блок "try", и поскольку адрес электронной почты недействителен, выбрасывается исключение.
  5. Блок "catch" перехватывает исключение и отображает сообщение об ошибке.

Множественные исключения

Несколько исключений можно использовать, чтобы скрипт мог обнаруживать несколько ситуаций.

Вы можете использовать несколько блоков if..else, или блок switch, или вложить несколько исключений. Эти исключения могут использовать разные классы исключений и возвращать разные сообщения об ошибках:

<?php class customException extends Exception { public function errorMessage() { //Сообщение об ошибке $errorMsg = 'Номер строки с ошибкой'.$this->getLine().' в '.$this->getFile() .': <b>'.$this->getMessage().'</b> не является допустимым адресом E-Mail'; return $errorMsg; } } $email = "[email protected]"; try { //Проверить e-mail if(filter_var($email, FILTER_VALIDATE_EMAIL) === FALSE) { //Если это недействительный адрес e-mail, выбросить исключение throw new customException($email); } //Проверьте, содержится ли "example" в адресе электронной почты if(strpos($email, "example") !== FALSE) { throw new Exception("$emailЯвляется примером адреса электронной почты"); } } catch (customException $e) { echo $e->errorMessage(); } catch(Exception $e) { echo $e->getMessage(); } ?>

Пояснение к примеру:

Приведенный выше код проверяет два условия, и если любое из условий не выполнено, выбрасывается исключение:

  1. Класс customException() создан как расширение старого класса исключений. Таким образом, он наследует все свойства и методы старого класса исключений.
  2. Создайте функцию errorMessage(). Если адрес e-mail недействителен, эта функция возвращает сообщение об ошибке.
  3. Присвойте переменной $email строку, которая является допустимым адресом электронной почты, но содержит строку "example".
  4. Выполните блок "try"; при первом условии исключение не выбрасывается.
  5. Поскольку адрес электронной почты содержит строку "example", второе условие вызывает исключение.
  6. Блок "catch" перехватывает исключение и отображает соответствующее сообщение об ошибке.

Если класс customException выбрасывает исключение, но customException не перехватывается, а перехватывается только базовое исключение, то исключение обрабатывается там.


Повторный выброс исключений

Иногда, когда выбрасывается исключение, вы можете захотеть обработать его иначе, чем стандартным способом. Вы можете перебросить исключение в блоке "catch".

Скрипты должны скрывать системные ошибки от пользователей. Системные ошибки могут быть важны для программистов, но пользователям они не интересны. Чтобы упростить работу пользователям, можно перебросить исключение с понятным пользователю сообщением:

<?php class customException extends Exception { public function errorMessage() { //Сообщение об ошибке $errorMsg = $this->getMessage().'не является допустимым адресом электронной почты.'; return $errorMsg; } } $email = "[email protected]"; try { try { //Проверьте, содержится ли "example" в адресе электронной почты if(strpos($email, "example") !== FALSE) { //Если это недопустимый адрес электронной почты, выбросьте исключение throw new Exception($email); } } catch(Exception $e) { //Повторно выбросить исключение throw new customException($email); } } catch (customException $e) { //Отобразить пользовательское сообщение echo $e->errorMessage(); } ?>

Пояснение к примеру:

Приведённый выше код проверяет, содержит ли адрес электронной почты строку "example". Если да, исключение выбрасывается повторно:

  1. Класс customException() создаётся как расширение старого класса исключений. Таким образом он наследует все свойства и методы старого класса исключений.
  2. Создайте функцию errorMessage(). Если адрес электронной почты недействителен, эта функция возвращает сообщение об ошибке.
  3. Присвойте переменной $email строку, которая является допустимым адресом электронной почты, но содержит строку "example".
  4. Блок "try" содержит другой блок "try", чтобы исключение можно было выбросить снова.
  5. Поскольку адрес электронной почты содержит строку "example", исключение срабатывает.
  6. Блок "catch" перехватывает исключение и повторно выбрасывает "customException".
  7. "customException" перехватывается, и отображается сообщение об ошибке.

Если исключение не перехвачено в текущем блоке "try", оно будет искать блок catch на более высоком уровне.


Установка обработчика исключений верхнего уровня

Функция set_exception_handler() может задать определяемую пользователем функцию, которая обрабатывает все неперехваченные исключения.

<?php function myException($exception) { echo "<b>Exception:</b> " , $exception->getMessage(); } set_exception_handler('myException'); throw new Exception('Произошло неперехваченное исключение'); ?>

Вывод приведённого выше кода следующий:

Exception: Uncaught Exception occurred

В приведённом выше коде нет блока "catch"; вместо этого запускается обработчик исключений верхнего уровня. Эта функция должна использоваться для перехвата всех исключений, которые не перехвачены.


Правила обработки исключений

  • Код, требующий обработки исключений, следует размещать внутри блока try, чтобы перехватывать потенциальные исключения.
  • Каждый блок try или throw должен иметь как минимум один соответствующий блок catch.
  • Использование нескольких блоков catch позволяет перехватывать разные виды исключений.
  • Исключение может быть выброшено (повторно выброшено) в блоке catch внутри блока try.

Короче говоря: если исключение выброшено, оно должно быть перехвачено.

Другие расширения