Обработка ошибок ================ Yii предоставляет полноценный функционал обработки ошибок на базе механизма обработки ошибок в РНР 5. В момент поступления пользовательского запроса создается экземпляр приложения, который регистрирует метод [handleError|CApplication::handleError] для обработки предупреждений и уведомлений, а также метод [handleException|CApplication::handleException] для обработки не пойманных исключений. Таким образом, если в процессе выполнения приложения возникают предупреждения, уведомления РНР или непойманные исключения, один из обработчиков ошибок получит управление и запустит необходимую процедуру обработки ошибок. > Tip|Подсказка: Регистрация обработчиков ошибок осуществляется в конструкторе приложения путем вызова функций РНР [set_exception_handler](http://php.net/manual/en/function.set-exception-handler.php) и [set_error_handler](http://php.net/manual/en/function.set-error-handler.php). Если вы не хотите, чтобы Yii обрабатывал ошибки и исключения, во [входном скрипте](/doc/guide/basics.entry) установите значение *false* константам `YII_ENABLE_ERROR_HANDLER` и `YII_ENABLE_EXCEPTION_HANDLER`. По умолчанию, метод [handleError|CApplication::handleError] (или [handleException|CApplication::handleException]) вызывает событие [onError|CApplication::onError] (или [onException|CApplication::onException]). Если ошибка (или исключение) не обрабатывается обработчиком события, он обращается за помощью к компоненту приложения [errorHandler|CErrorHandler]. Вызов исключений ------------------ Вызов исключений в Yii ничем не отличается от вызова обычного исключения РНР. В случае необходимости, вызов исключения осуществляется следующим образом: ~~~ [php] throw new ExceptionClass('ExceptionMessage'); ~~~ Yii определяет три класса для исключений: [CException], [CDbException] и [CHttpException]. [CException] — типовой класс исключения. [CDbException] представляет исключения, вызываемые некоторыми операциями базы данных. [CHttpException] отвечает за исключения, которые отображаются конечному пользователю, и содержит свойство [statusCode|CHttpException::statusCode], соответствующее коду состояния НТТР. Класс исключения определяет также, каким образом отображается ошибка. Об этом будет рассказано ниже. > Tip|Подсказка: Вызов исключения [CHttpException] — это простой способ сообщить об ошибках, > вызванных неверными действиями пользователя. Например, если пользователь указывает в адресе URL > неверный идентификатор записи, для отображения ошибки 404 (страница не найдена) мы можем > выполнить следующее действие: > > ~~~ > [php] > // если идентификатора записи не существует > throw new CHttpException(404,'Указанная запись не найдена'); > ~~~ Отображение ошибок ----------------- В момент, когда компонент приложения [CErrorHandler] получает ошибку, выбирается соответствующее представление для её отображения. Если предполагается, что сообщение об ошибке должно отображаться конечным пользователям, например [CHttpException], то используется представление с именем `errorXXX`, где `XXX` соответствует коду состояния НТТР (400, 404, 500 и т.д.). Если же это внутренняя ошибка и отображаться она должна только разработчикам, используется представление с именем `exception`. В последнем случае будет отображен весь стек вызовов, а также указание на строку возникновения ошибки. > Info|Инфо: Если приложение запускается в [производственном режиме](/doc/guide/basics.entry#debug-mode), все ошибки, включая внутренние, отображаются с использованием представления `errorXXX`. Это сделано из соображений безопасности, поскольку стек вызова может содержать важную информацию. В этом случае для выявления причин возникновения ошибки необходимо использовать протокол ошибок. [CErrorHandler] осуществляет поиск файла, соответствующего представлению, в следующем порядке: 1. `WebRoot/themes/ThemeName/views/system`: папка системных представлений текущей темы оформления; 2. `WebRoot/protected/views/system`: папка системных представлений приложения, используемая по умолчанию; 3. `yii/framework/views`: папка стандартных системных представлений, предоставляемых фреймворком. Следовательно, если нам необходимо изменить внешний вид сообщений, мы можем просто создать файлы представлений ошибок в папке системных представлений приложения или темы. Каждый файл представления — это обычный РНР-скрипт, состоящий преимущественно из HTML-кода. Подробнее с этим можно разобраться, просто изучив используемые по умолчанию файлы, расположенные в папке фреймворка с именем `view`. Управление отображением ошибок в действии контроллера ----------------------------------------------------- Yii позволяет использовать [действие контроллера](/doc/guide/basics.controller#action) для отображения ошибок. Для этого необходимо задать обработчик ошибок в настройках приложения: ~~~ [php] return array( … 'components'=>array( 'errorHandler'=>array( 'errorAction'=>'site/error', ), ), ); ~~~ Выше мы задали маршрут `site/error`, ведущий к действию `error` контроллера `SiteController`, свойству [CErrorHandler::errorAction]. Если необходимо, можно использовать другой маршрут. Код действия `error` должен выглядеть примерно так: ~~~ [php] 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`: часть кода, где возникла ошибка. > Tip|Подсказка: Проверка [CErrorHandler::error] на пустое значение делается, т.к. действие `error` может быть вызвано пользователем напрямую. Так как мы передаём массив `$error` представлению, он будет автоматически развёрнут в отдельные переменные, поэтому мы можем обращаться к ним напрямую, как `$code` или `$type`. Протоколирование сообщений -------------------------- Если возникает ошибка, то соответствующее сообщение с уровнем `error` всегда вносится в лог. В случае, если ошибка — результат предупреждения или уведомления РНР, сообщению присваивается категория `php`, если же ошибка вызвана не пойманным исключением, сообщению присваивается категория `exception.ExceptionClassName` (в случае [CHttpException] к категории добавляется [код состояния|CHttpException::statusCode]). Для отслеживания ошибок, возникающих в процессе выполнения приложения, можно использовать функционал [журналирования](/doc/guide/topics.logging).