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

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

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

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

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

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

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

При указанной конфигурации количество строк исходного кода, отображаемых на страницах с исключениями, будет равно 20.

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

use Yii;
use yii\base\ErrorException;

try {
    10/0;
} catch (ErrorException $e) {
    Yii::warning("Division by zero.");
}

// execution continues...

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

use yii\web\NotFoundHttpException;

throw new NotFoundHttpException();

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

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

По умолчанию обработчик ошибок отображает ошибки с помощью двух представлений:

  • @yii/views/errorHandler/error.php: используется, когда должны отображаться ошибки без информации о стеке вызовов. Когда YII_DEBUG ложно, это единственное представление ошибки, которое будет отображаться.
  • @yii/views/errorHandler/exception.php: используется, когда должны отображаться ошибки с информацией стека вызовов.

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

Использование действий с ошибками

Лучшим способом настройки отображения ошибки является использование специальных действий с ошибками. Для этого сначала настройте свойство errorAction компонента errorHandler следующим образом:

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

Свойство errorAction принимает маршрут к действию. Вышеупомянутая конфигурация заявляет, что, когда ошибка должна отображаться без информации стека вызовов, должно выполняться действие site/error. Вы можете создать действие 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, код ошибки, стек вызовов ошибок и т. д.

Настройка формата ответа на ошибку

Обработчик ошибок отображает ошибки в соответствии с настройкой формата ответа. Если формат ответа - 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
    }
}