Обробка помилок
===============

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