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

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).