PHP

Исключения PHP. Часть 2 из 2

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

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

Чтобы создать расширенное исключение необходимо построить класс исключений, расширяющий класс Exception. Создадим пользовательское исключение UserException для нашего класса, построенного в предыдущем уроке серии:
class UserException extends Exception
{
   public function __construct($error_code)
   {
      parent::__construct(UserErrors::getErrorMessage($error_code), $error_code);
      Logger::newMessage($this);
   }
}

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

Обновим код для использования нашего нового класса UserException:
private static function _validateUserId($user_id)
{
   if( !is_numeric($user_id) && $user_id != 'error' ) {
      throw new UserException(UserErrors::INVALIDID);
   }
   return $user_id;
}

Так как исключение автоматически заносит себя в журнал, можно Полевой игрок поймал исключение: опустить данную операцию в блоке try-catch:
...
...
} catch( Exception $e ) {
   echo "Полевой игрок поймал исключение: #{$e->getCode()}";
   //Logger::newMessage($e);
}

Теперь изменим код в других местах класса User, где ожидается появление исключений.

Класс User:
...
...
...
public function __get($value) {
   $value = "_{$value}";
   if( !isset($this->$value) ) {
      throw new UserException(UserErrors::NOTASETTING);
   }
   return $this->$value;
}
 
public function __set($name, $value) {
   switch($name) {
      case 'user_id':
         $user_id = self::_validateUserId($value);
         $this->_user_id = $user_id;
         break;
 
      case 'user_email':
         $user_email = self::_validateUserEmail($value);
         $this->_user_email = $user_email;
         break;
 
      case 'user_password':
         $user_password = self::_validateUserPassword($value);
         $this->_user_password = $user_password;
         break;
 
      default:
         throw new UserException(UserErrors::NOTASETTING);
         break;
   }
   return true;
}
 
private static function _getUserRecord($user_id)
{
   ...
   ...
   ...
   switch($user_id) {
      ...
      ...
      ...
      default:
         throw new UserException(UserErrors::DOESNOTEXIST);
         break;
   }
}

И попробуем генерировать три исключения:
$user = new User(1);
try {
   $user->user_email = 'invalid email';
} catch( Exception $e ) {
   echo "Полевой игрок поймал исключение: #{$e->getCode()}<br />";
}
  
try {
   echo $user->setting_that_doesnt_exist;
} catch( Exception $e ) {
   echo "Полевой игрок поймал исключение: #{$e->getCode()}<br />";
}
  
try {
   //id пользователя не существует
   $user = new User(3);
} catch( Exception $e ) {
   echo "Полевой игрок поймал исключение: #{$e->getCode()}<br />";
}

Ну и какие выгоды сулит расширенное исключение, кроме пользовательского конструктора? Такое улучшение можно легко реализовать с помощью класса Exception без дополнительных действий. Но с помощью пользовательских исключений мы можем:

Переписать функцию __construct и реализовать собственный код;
Организовать исключение в зависимости от типа объекта;
использовать блок множественных перехватов для обработки исключений в зависимости от типа!


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

Наш блок try-catch предназначен для обработки обычного типа исключений Exception — так обеспечивается обработка ошибок для исключений незапланированных типов.

Изменим наш код так, чтобы исключение UserException обрабатывалось особенным образом. Будем использовать еще один блок перехвата, чтобы неожиданные исключения продолжали обрабатываться.
try {
   $user = new User(1);
   $user->user_password = '123';
} catch( UserException $e ) {
   echo "Полевой игрок поймал исключение UserException: #{$e->getCode()}<br />";
} catch( Exception $e ) {
   echo "Полевой игрок поймал исключение Exception:: #{$e->getCode()}<br />";
}
  
try {
   //Использование аргумента 'error' в классе User имитирует
   //ошибку в библиотеке SQL
   $user = new User('error');
} catch( UserException $e ) {
   echo "Полевой игрок поймал исключение UserException: #{$e->getCode()}<br />";
} catch( Exception $e ) {
   echo "Полевой игрок поймал исключение Exception:: #{$e->getCode()}<br />";
}

Исключения UserException и Exception будут обрабатываться по-разному. Может показаться, что пользы в раздельной обработке нет. Но самое очевидное применение - показ пользователю или запись в журнал только определенных исключений.

Заключение
Исключения PHP позволяют организовать простую и централизованную обработку различных ошибок во время выполнения кода.
Теги:
Исключения
Добавлено: 02 Мая 2018 20:20:04 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...