Все ленты — последние статьи

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

В PHP5 как и в других мощных языках программирования (например Java) существует механизм выброса и перехвата исключительных ситуаций.

Для этого необходимо поместить потенциально небезопасный код в блок try для перехвата исключения. Каждый try должен сопровождаться как минимум одним блоком catch.

Множественные блоки catch можно использовать для перехвата исключений различных классов. Меньше слов — больше дела:


01 class Generic
02 {
03
04 private $someVar;
05
06 public function __construct($someVar)
07 {
08 $this->someVar = $someVar;
09 }
10
11 public function testValue($someOtherVar)
12 {
13 if($someOtherVar > 3) {
14 throw new Exception('Значение параметра не может быть больше 3!');
15 } else {
16 echo $this->someVar + $someOtherVar;
17 }
18 }
19 }
20
21 $gen = new Generic(3);
22 $gen->testValue(4);

Этот фрагмент кода превосходно демонстрирует процесс выброса исключения. Если вы сейчас запустите страницу с этим кодом, то получите сообщение на подобии этого:

Fatal error: Uncaught exception ‘Exception’ with message ‘Parameter can not be larger then 3!’ in C:wampwwwprivatcodeforestexceptionsindex.php:15 Stack trace: #0 C:wampwwwprivatcodeforestexceptionsindex.php(23): Generic->testValue(4) #1 {main} thrown in C:wampwwwprivatcodeforestexceptionsindex.php on line 15

Это произошло из-за отсутствия блока try-catch. Исправим ситуацию следующим образом:
01 try
02 {
03 $gen = new Generic(3);
04 $gen->testValue(4);
05 } catch (Exception $e) {
06 // обработка исключения
07 echo 'Поймали исключение<br />';
08 echo 'Сообщение: ' . $e->getMessage() . '<br />';
09 echo 'Дополнительный текст!';
10 }

Теперь мы успешно поймали наше исключение. Доказательство этому сообщение на экране.

Так же существует возможность получения детальной информации при перехвате исключительной ситуации. Это полезно тогда, когда у вас выбрасываются десятки или сотни исключений. Для того, чтобы быстро найти код, где это произошло, можно воспользоваться специальными методами:
01 try
02 {
03 $gen = new Generic(3);
04 $gen->testValue(4);
05 } catch (Exception $e) {
06 // code to handle the Exception
07 echo 'Error :' . $e->getMessage() . '<br />';
08 echo 'Code :' . $e->getCode() . '<br />';
09 echo 'File :' . $e->getFile() . '<br />';
10 echo 'Line :' . $e->getLine() . '<br />';
11 exit();
12 }

Этот пример не сильно отличается от прошлого. Тут мы используем методы объекта, сгенерированного в блоке catch для получения более детальной информации об исключении, а именно само сообщение об ошибке, код ошибки (если такой имеется), файл и линия, где данное исключение было обработано.

Теперь в принципе вам должны быть ясны преимущества исключений. Обратите внимание на этот простой механизм, который может поможет вам отлавливать недочёты даже в самых “глубоких” местах. В добавок он даёт вам детальную информацию об ошибке, что позволит вам быстро всё исправить.

Вот ещё пример:
01 class Generic
02 {
03
04 private $someVar, $result;
05 const NUM_ERROR = 1;
06 const ANY_ERROR = 2;
07
08 public function __construct($someVar)
09 {
10 $this->someVar = $someVar;
11 }
12
13 public function testValue($someOtherVar)
14 {
15 if($someOtherVar > 3) {
16 throw new Exception('Значение параметра не божет быть больше 3!', self::NUM_ERROR);
17 } else {
18 $this->result = $this->someVar + $someOtherVar;
19 echo $this->result . '<br />';
20 }
21 }
22
23 public function otherMethod()
24 {
25 if($this->result > 4) {
26 throw new Exception('Результат больше 4.', self::ANY_ERROR);
27 }
28 }
29 }
30
31 // Начинаем охоту
32 try
33 {
34 $gen = new Generic(3);
35 $gen->testValue(2);
36 $gen->otherMethod();
37 } catch (Exception $e) {
38 if($e->getCode() == 1) {
39 die ($e->getMessage());
40 } else {
41 echo 'Error :' . $e->getMessage() . '<br />';
42 echo 'File :' . $e->getFile() . '<br />';
43 echo 'Line :' . $e->getLine() . '<br />';
44 exit();
45 }
46 }

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

Но это ещё не всё, что вы можете делать. Вы так же можете создавать свои типы исключений. В этом нет ничего сложного. Нам нужно просто создать дополнительный класс, который будет наследовать класс exception.

42 error_log($this->getMessage(), 1, Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра.'">'Этот адрес электронной почты защищен от спам-ботов. У вас должен быть включен JavaScript для просмотра.');

В этом примере мы создали наш собственный тип исключения CustomException.

При вызове logError() в зависимости от типа ошибки, будет осуществляться соответствующее действие (запись в логи или письмо админу).

В PHP5 существует метод set_exception_handler, который позволяет определить функцию перехватывающую все не отловленные исключения.
1 function myException($exception)
2 {
3 echo "<strong>Exception:</strong> " , $exception->getMessage();
4 }
5
6 set_exception_handler('myException');
7
8 throw new Exception('Новое исключение');

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