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 фрэймворки используют данную технику для регистрации всех ошибок, что позволяет быстро их устранить, тем самым строить настолько безопасные системы насколько это возможно.
Теги:
Обработка исключений
Добавлено: 03 Мая 2018 06:50:39 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...