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

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

- Все не фатальные ошибки PHP (то есть warning, notice) конвертируются в исключения, которые можно перехватывать.
- Исключения и фатальные ошибки PHP отображаются в режиме отладки с детальным стеком вызовов и исходным кодом.
- Можно использовать для отображения ошибок действие контроллера.
- Поддерживаются различные форматы ответа.

По умолчанию обработчик ошибок включен. Вы можете выключить его объявив константу `YII_ENABLE_ERROR_HANDLER` со значением `false` во входном скрипте вашего приложения.

## Использование обработчика ошибок ¶

Обработчик ошибок регистрируется в качестве компонента приложения с именем `errorHandler`. Вы можете настраивать его следующим образом:

    return [
        'components' => [
            'errorHandler' => [
                'maxSourceLines' => 20,
            ],
        ],
    ];

С приведённой выше конфигурацией на странице ошибки будет отображаться до 20 строк исходного кода.

Как уже было упомянуто, обработчик ошибок конвертирует все не фатальные ошибки PHP в перехватываемые исключения. Это означает что можно поступать с ошибками следующим образом:

    use Yii;
    use yii\base\ErrorException;

    try {
        10/0;
    } catch (ErrorException $e) {
        Yii::warning("Деление на ноль.");
    }

    // можно продолжать выполнение

Если вам необходимо показать пользователю страницу с ошибкой, говорящей ему о том, что его запрос не верен или не должен был быть сделан, вы можете выкинуть исключение HTTP, такое как yii\web\NotFoundHttpException. Обработчик ошибок корректно выставит статус код HTTP для ответа и использует подходящий вид страницы ошибки.

    use yii\web\NotFoundHttpException;

    throw new NotFoundHttpException();

## Настройка отображения ошибок ¶

Обработчик ошибок меняет отображение ошибок в зависимости от значения константы `YII_DEBUG`. При `YII_DEBUG` равной `true` (режим отладки), обработчик ошибок будет отображать для облегчения отладки детальный стек вызовов и исходный код. При `YII_DEBUG` равной `false` отображается только сообщение об ошибке, тем самым не позволяя получить информацию о внутренностях приложения.

> Информация: Если исключение является наследником yii\base\UserException, стек вызовов не отображается вне зависимости от значения `YII_DEBUG` так как такие исключения считаются ошибками пользователя и исправлять что-либо разработчику не требуется.

По умолчанию обработчик ошибок показывает ошибки используя два представления:

- `@yii/views/errorHandler/error.php`: используется для отображения ошибок БЕЗ стека вызовов. При `YII_DEBUG` равной `false` используется только это преставление.
- `@yii/views/errorHandler/exception.php`: используется для отображения ошибок СО стеком вызовов.

Вы можете настроить свойства errorView и exceptionView для того, чтобы использовать свои представления.

### Использование действий для отображения ошибок ¶

Лучшим способом изменения отображения ошибок является использование действий путём конфигурирования свойства errorAction компонента `errorHandler`:

    // ...
    'components' => [
        // ...
        'errorHandler' => [
            'errorAction' => 'site/error',
        ],
    ]

Свойство errorAction принимает маршрут действия. Конфигурация выше означает, что для отображения ошибки без стека вызовов будет использовано действие `site/error`.

Само действие можно реализовать следующим образом:

    namespace app\controllers;

    use Yii;
    use yii\web\Controller;

    class SiteController extends Controller
    {
        public function actions()
        {
            return [
                'error' => [
                    'class' => 'yii\web\ErrorAction',
                ],
            ];
        }
    }

Приведённый выше код задаёт действие `error` используя класс yii\web\ErrorAction, который рендерит ошибку используя отображение `error`.

Вместо использования yii\web\ErrorAction вы можете создать действие `error` как обычный метод:

    public function actionError()
    {
        $exception = Yii::$app->errorHandler->exception;
        if ($exception !== null) {
            return $this->render('error', ['exception' => $exception]);
        }
    }

Вы должны создать файл представления `views/site/error.php`. В этом файле, если используется yii\web\ErrorAction, вам доступны следующие переменные:

- `name`: имя ошибки;
- `message`: текст ошибки;
- `exception`: объект исключения, из которого можно получить дополнительную информацию, такую как статус HTTP, код ошибки, стек вызовов и т.д.

> Информация: Если вы используете шаблоны приложения basic или advanced, действие error и файл представления уже созданы за вас.

### Изменение формата ответа ¶

Обработчик ошибок отображает ошибки в соответствии с выбранным форматом ответа. Если формат ответа задан как `html`, будут использованы представления для ошибок и исключений, как описывалось ранее. Для остальных форматов ответа обработчик ошибок присваивает массив данных, представляющий ошибку свойству yii\web\Response::$data. Оно далее конвертируется в необходимый формат. Например, если используется формат ответа `json`, вы получите подобный ответ:

    HTTP/1.1 404 Not Found
    Date: Sun, 02 Mar 2014 05:31:43 GMT
    Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=UTF-8

    {
        "name": "Not Found Exception",
        "message": "The requested resource was not found.",
        "code": 0,
        "status": 404
    }

Изменить формат можно в обработчике события `beforeSend` компонента `response` в конфигурации приложения:

    return [
        // ...
        'components' => [
            'response' => [
                'class' => 'yii\web\Response',
                'on beforeSend' => function ($event) {
                    $response = $event->sender;
                    if ($response->data !== null) {
                        $response->data = [
                            'success' => $response->isSuccessful,
                            'data' => $response->data,
                        ];
                        $response->statusCode = 200;
                    }
                },
            ],
        ],
    ];

Приведённый код изменит формат ответа на подобный:

    HTTP/1.1 200 OK
    Date: Sun, 02 Mar 2014 05:31:43 GMT
    Server: Apache/2.2.26 (Unix) DAV/2 PHP/5.4.20 mod_ssl/2.2.26 OpenSSL/0.9.8y
    Transfer-Encoding: chunked
    Content-Type: application/json; charset=UTF-8

    {
        "success": false,
        "data": {
            "name": "Not Found Exception",
            "message": "The requested resource was not found.",
            "code": 0,
            "status": 404
        }
    }