PHP

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

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

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

Множественные блоки catch можно использовать для перехвата исключений различных классов. Меньше слов - больше дела:
 	class Generic
 	  {
 	 
 	      private $someVar;
	 
 	      public function __construct($someVar)
 	      {
 	          $this->someVar = $someVar;
 	      }
 	 
 	      public function testValue($someOtherVar)
	      {
 	          if($someOtherVar > 3) {
 	              throw new Exception('Значение параметра не божет быть больше 3!');
	          } else {
 	              echo $this->someVar + $someOtherVar;
	          }
 	      }
 	  }
 	 
 	  $gen = new Generic(3);
 	  $gen->testValue(4);

Этот фрагмент кода превосходно демонстрирует процесс выброса исключения. Если вы сейчас запустите страницу с этим кодом, то получите сообщение на подобии этого:
Fatal error: Uncaught exception ‘Exception’ with message ‘Parameter can not be larger then 3!’ in C:\wamp\www\privat\codeforest\exceptions\index.php:15 Stack trace: #0 C:\wamp\www\privat\codeforest\exceptions\index.php(23): Generic->testValue(4) #1 {main} thrown in C:\wamp\www\privat\codeforest\exceptions\index.php on line 15

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

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

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

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

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

Вот ещё пример:
 	class Generic
 	{
 	 
 	    private   $someVar, $result;
 	    const     NUM_ERROR       = 1;
 	    const     ANY_ERROR       = 2;
 	 
 	    public function __construct($someVar)
 	    {
 	        $this->someVar = $someVar;
 	    }
 	 
 	    public function testValue($someOtherVar)
 	    {
 	        if($someOtherVar > 3) {
 	            throw new Exception('Значение параметра не божет быть больше 3!', self::NUM_ERROR);
 	        } else {
 	            $this->result = $this->someVar + $someOtherVar;
 	            echo $this->result . '<br />';
 	        }
 	    }
 	 
 	    public function otherMethod()
 	    {
 	        if($this->result > 4) {
 	            throw new Exception('Результат больше 4.', self::ANY_ERROR);
 	        }
 	    }
 	}
 	 
 	// Начинаем охоту
 	try
 	{
 	      $gen = new Generic(3);
 	      $gen->testValue(2);
 	      $gen->otherMethod();
 	} catch (Exception $e) {
 	      if($e->getCode() == 1) {
 	          die ($e->getMessage());
 	      } else {
 	          echo 'Error :' . $e->getMessage() . '<br />';
 	          echo 'File :' . $e->getFile() . '<br />';
 	          echo 'Line :' . $e->getLine() . '<br />';
 	          exit();
 	      }
 	}

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

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

Кроме унаследованных методов, вы так же можете добавить и свои. Вот пример:
 	class Generic
 	  {
 	 
 	      private   $someVar, $result;
 	      const     NUM_ERROR       = 1;
 	      const     ANY_ERROR       = 2;
 	 
 	      public function __construct($someVar)
 	      {
 	          $this->someVar = $someVar;
 	      }
 	 
 	      public function testValue($someOtherVar)
 	      {
	          if($someOtherVar > 3) {
 	              throw new CustomException('Значение параметра не божет быть больше 3!', self::NUM_ERROR);
 	          } else {
 	              $this->result = $this->someVar + $someOtherVar;
 	              echo $this->result . '<br />';
 	          }
 	      }
 	 
 	      public function otherMethod()
 	      {
 	          if($this->result > 4) {
 	              throw new CustomException('Результат больше 4.', self::ANY_ERROR);
 	          }
 	      }
 	  }
 	 
 	  class CustomException extends Exception
 	  {
 	 
 	      public function logError()
 	      {
 	            // Записать в логи сервера
 	            if($this->getCode() == Generic::NUM_ERROR){
 	                error_log($this->getMessage(), 0);
 	            }
	            // Сообщить админу по email
 	            else if($this->getCode() == Generic::ANY_ERROR){
 	                error_log($this->getMessage(), 1, 'sysadmin@domain.com');
 	            }
 	      }
 	}
 	 
 	  // Отлавливаем
 	  try
 	  {
 	        $gen = new Generic(3);
 	        $gen->testValue(2);
 	        $gen->otherMethod();
 	  } catch (CustomException $e) {
 	        $e->logError();
 	  }

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

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

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

PHP исключения это очень важный аспект, который должен использоваться в каждом крупном проекте. Многие PHP фрэймворки используют данную технику для регистрации всех ошибок, что позволяет быстро их устранить, тем самым строить настолько безопасные системы насколько это возможно.
Добавлено: 19 Августа 2013 11:43:41 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...