0 follower

Обработка ошибок

Yii предоставляет полноценный функционал обработки ошибок на базе механизма обработки ошибок в РНР 5. В момент поступления пользовательского запроса создается экземпляр приложения, который регистрирует метод handleError для обработки предупреждений и уведомлений, а также метод handleException для обработки непойманных исключений. Таким образом, если в процессе выполнения приложения возникают предупреждения, уведомления РНР или непойманные исключения, один из обработчиков ошибок получит управление и запустит необходимую процедуру обработки ошибок.

Подсказка: Регистрация обработчиков ошибок осуществляется в конструкторе приложения путем вызова функций РНР set_exception_handler и set_error_handler. Если вы не хотите, чтобы Yii обрабатывал ошибки и исключения, во входном скрипте установите значение false константам YII_ENABLE_ERROR_HANDLER и YII_ENABLE_EXCEPTION_HANDLER.

По умолчанию, метод errorHandler (или exceptionHandler) вызывает событие onError (или onException). Если ошибка (или исключение) не обрабатывается обработчиком события, он обращается за помощью к компоненту приложения errorHandler.

1. Вызов исключений

Вызов исключений в Yii ничем не отличается от вызова обычного исключения РНР. В случае необходимости, вызов исключения осуществляется следующим образом:

throw new ExceptionClass('ExceptionMessage');

Yii определяет два класса для исключений: CException и CHttpException. Первый является типовым классом исключения, а второй отвечает за исключения, которые отображаются конечному пользователю. Кроме того, второй класс имеет свойство statusCode, соответствующее коду состояния НТТР. Класс исключения определяет также, каким образом отображается ошибка. Об этом будет рассказано ниже.

Подсказка: Вызов исключения CHttpException - это простой способ сообщить об ошибках, вызванных неверными действиями пользователя. Например, если пользователь указывает в адресе URL неверный идентификатор поста, для отображения ошибки 404 (страница не найдена) мы можем выполнить следующее действие:

// если идентификатора поста не существует
throw new CHttpException(404,'Указанный пост не найден');

2. Отображение ошибок

В момент, когда компонент приложения CErrorHandler получает ошибку, выбирается соответствующее представление для её отображения. Если предполагается, что сообщение об ошибке должно отображаться конечным пользователям, например CHttpException, то используется представление с именем errorXXX, где XXX соответствует коду состояния НТТР (400, 404, 500 и т.д.). Если же это внутренняя ошибка и отображаться она должна только разработчикам, используется представление с именем exception. В последнем случае будет отображен весь стек вызовов, а также указание на строку возникновения ошибки.

Инфо: Если приложение запускается в производственном режиме, все ошибки, включая внутренние, отображаются с использованием представления errorXXX. Это сделано из соображений безопасности, поскольку стек вызова может содержать важную информацию. В этом случае для выявления причин возникновения ошибки необходимо использовать протокол ошибок.

CErrorHandler осуществляет поиск файла, соответствующего представлению, в следующем порядке:

  1. WebRoot/themes/ThemeName/views/system: папка системных представлений текущей темы оформления;

  2. WebRoot/protected/views/system: папка системных представлений приложения, используемая по умолчанию;

  3. yii/framework/views: папка стандартных системных представлений, предоставляемых фреймворком.

Следовательно, если нам необходимо изменить внешний вид сообщений, мы можем просто создать файлы представлений ошибок в папке системных представлений приложения или темы. Каждый файл представления - это обычный РНР-скрипт, состоящий преимущественно из HTML-кода. Подробнее с этим можно разобраться, просто изучив используемые по умолчанию файлы, расположенные в папке фреймворка с именем view.

Управление отображением ошибок в действии контроллера

Начиная с версии 1.0.6 Yii позволяет использовать действие контроллера для отображения ошибок. Для этого необходимо задать обработчик ошибок в настройках приложения:

return array(
    ......
    'components'=>array(
        'errorHandler'=>array(
            'errorAction'=>'site/error',
        ),
    ),
);

Выше мы задали маршрут site/error, ведущий к действию error контроллера SiteController, свойству CErrorHandler::errorAction. Если необходимо, можно использовать другой маршрут.

Код действия error должен выглядеть примерно так:

public function actionError()
{
    if($error=Yii::app()->errorHandler->error)
        $this->render('error', $error);
}

Сначала мы получаем подробную информацию об ошибке из CErrorHandler::error. Если она не пуста — отображаем её в представлении error. Информация, получаемая из CErrorHandler::error является массивом, содержащим следующие данные:

  • code: код ответа HTTP (например, 403 или 500);
  • type: тип ответа (например, CHttpException или PHP Error);
  • message: текст сообщения;
  • file: имя PHP-скрипта, в котором возникла ошибка;
  • line: номер строки, на которой возникла ошибка;
  • trace: стэк вызовов ошибки;
  • source: часть кода, где возникла ошибка.

Подсказка: Проверка CErrorHandler::error на пустое значение делается, т.к. действие error может быть вызвано пользователем напрямую. Так как мы передаём массив $error представлению, он будет автоматически развёрнут в отдельные переменные, поэтому мы можем обращаться к ним напрямую, как $code или $type.

3. Протоколирование сообщений

Если возникает ошибка, то соответствующее сообщение с уровнем error всегда вносится в лог. В случае, если ошибка - результат предупреждения или уведомления РНР, сообщению присваивается категория php, если же ошибка вызвана непойманным исключением, сообщению присваивается категория exception.ExceptionClassName (в случае CHttpException к категории добавляется код состояния). Для отслеживания ошибок, возникающих в процессе выполнения приложения, можно использовать функционал журналирования.