Обработка ошибок ¶
В состав 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
}
}
Обработка ошибок
Раздел в разработке.
Обработка ошибок в Yii происходит несколько иначе, чем в обычном PHP. Во-первых, все нефатальные ошибки в Yii преобразуются в исключения:
use yii\base\ErrorException;
use Yii;
try {
10/0;
} catch (ErrorException $e) {
Yii::warning("Попытка деления на ноль.");
}
// можно продолжать выполнение
Как это видно из примера, вы можете обрабатывать ошибки, используя конструкцию try
—catch
.
Во-вторых, даже фатальные ошибки в Yii показываются в красивом виде. Это значит, что при отладке кода, вы можете отслеживать причины фатальных
ошибок. Это позволяет быстрее находить причины возникших проблем.
Рендеринг ошибок в произвольном действии контроллера
Обычная страница вывода ошибок Yii не только хороша в разработке, но и приемлема для уже развернутых проектов, если YII_DEBUG
выключена в начальном загрузочном скрипте index.php
. Но иногда хочется изменить внешний вид страницы с ошибками, чтобы лучше приспособить ее под свой проект.
Самый легкий способ создать свою страницу для отображения ошибок — использовать свое действие (action) для рендеринга сообщений об ошибке.
Сначала нужно дать приложению понять, что вы хотите использовать свое действие для обработки ошибок. Для этого нужно сконфигурировать компонент errorHandler
в конфигурационном файле приложения:
// ...
'components' => [
// ...
'errorHandler' => [
'errorAction' => 'site/error',
],
]
С вышеуказанной конфигурацией, если происходит ошибка, Yii запустит действие error
контроллера site
. Это действие запрашивает у компонента errorHandler
, было ли выброшено исключение, и, если да, отображает соответствующий вид, передавая ему объект исключения в качестве параметра.
public function actionError()
{
$exception = \Yii::$app->errorHandler->exception;
if ($exception !== null) {
return $this->render('error', ['exception' => $exception]);
}
}
После создания action
нужно создать соответствующий вид, который и будет отображать информацию об исключении. Объект исключения, передаваемый в вид, имеет
следующие свойства:
statusCode
: HTTP статус (например, 403, 500). Доступен только для [[yii\web\HttpException|HTTP exceptions]].code
: код исключения.message
: сообщение об ошибке.file
: имя файла PHP скрипта, в котором произошла ошибка.line
: номер строки в коде, где произошла ошибка.trace
: стэк вызовов, приведших к ошибке.
Рендеринг ошибок без создания отдельного действия
Вместо создания отдельного действия внутри контроллера Site, вы можете просто указать Yii какой класс использовать для обработки ошибок:
public function actions()
{
return [
'error' => [
'class' => 'yii\web\ErrorAction',
],
];
}
После задания вышеуказанной связки ошибки с классом обработчиком, создайте вид views/site/error.php
, который будет использоваться автоматически.
Виду передаются три параметра:
$name
: название ошибки$message
: сообщение об ошибке$exception
: обрабатываемое исключение
Объект $exception
имеет те же свойства, которые были указаны ранее.
Search code, repositories, users, issues, pull requests…
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Search code, repositories, users, issues, pull requests…
Provide feedback
Saved searches
Use saved searches to filter your results more quickly
Sign up
Вступление
В сегодняшнем уроке мы покажем как отловить ошибки и исключения в Yii, а также рассмотрим несколько возможных вариантов развития событий.
Не знакомы с Yii? Наверстать упущенное можно, прочитав статью Знакомство с фрэймворком Yii и серию Разработка на базе Yii2.
В чём разница между ошибками и исключениями?
Ошибки — непредвиденные дефекты, с которыми чаще всего сталкиваются пользователи. Как правило, возникновение ошибок приводит к завершению работы программы. В этом случае важно не только сохранить лицо перед пользователем, но и проинформировать разработчика о возникшей ситуации для её дальнейшего устранения.
Исключения происходят по инициативе разработчиков в потенциальных местах, где могут возникнуть ошибки. Для выброса исключения разработчик вызывает функцию throw(), а в дальнейшем может осуществить перехват.
Как эти процессы протекают в Yii?
В Yii, не фатальные PHP ошибки (заметки и предупреждения) отлавливаются, что даёт возможность должным образом на них среагировать. Все эти исключения могут направляться на определённый экшен контроллера. Также вы можете повлиять на формат отображения данных ошибок: HTML, JSON, XML и т.д.
Исключения и фатальные PHP ошибки можно увидеть только если код работает в отладочном режиме. В этом случае Yii выведет всю подробную информацию об ошибке, включая фрагмент проблемного кода (пример показан в ковер-изображении к данному уроку).
Возникновение фатальных ошибок останавливает работу приложения. К примеру, может возникнуть ситуация нехватки памяти, произойти попытка создания объекта несуществующего класса или вызов неизвестной функции.
К примеру:
1 |
$t = new Unknownobject(); |
Давайте же рассмотрим парочку примеров, где мы покажем как можно отловить ошибки/исключения, и обработать их.
Конфигурация обработчика ошибок и исключений
Для начала нам нужно внести кое-какие записи в файл конфигурации frontend/config/main.php. Как показано ниже, в этом файле определён компонент errorHandler. Данный пример взят из моей серии по организации стартапа Meeting Planner. Взгляните на конфигурацию errorHandler
в разделе components
:
1 |
<?php
|
2 |
$params = array_merge( |
3 |
require(__DIR__ . '/params.php'), |
4 |
require(__DIR__ . '/params-local.php') |
5 |
);
|
6 |
return [ |
7 |
'id' => 'mp-frontend', |
8 |
'name' => 'Meeting Planner', |
9 |
'basePath' => dirname(__DIR__), |
10 |
'bootstrap' => ['log','\common\components\SiteHelper'], |
11 |
'controllerNamespace' => 'frontend\controllers', |
12 |
'catchAll'=> [], |
13 |
'components' => [ |
14 |
'assetManager' => [...], |
15 |
...
|
16 |
'errorHandler' => [ |
17 |
'errorAction' => 'site/error', |
18 |
'maxSourceLines' => 20, |
19 |
],
|
20 |
...
|
21 |
],
|
22 |
];
|
В вышеприведённом примере определено, что при возникновении ошибки errorAction
направит пользователя на экшен error SiteController-а.
Если более подробно, то Yii предлагает целый ряд конфигурационных настроек к компоненту errorHandler
для редиректа и обработки информации:
Свойство | Тип | Описание |
---|---|---|
$callStackItemView | строка | Путь к файлу, в котором будет происходить рендеринг информации об ошибках. Пример: ‘@yii/views/errorHandler/callStackItem.php’ |
$displayVars | массив | Список определённых PHP переменных, которые должны отображаться в специальной секции отображения ошибок. Примеру: [‘_GET’, ‘_POST’, ‘_FILES’, ‘_COOKIE’, ‘_SESSION’] |
$errorAction | строка | Маршрут (site/error ) к контроллеру и экшену в котором будут обрабатываться ошибки. |
$errorView | строка | Путь к файлу, в котором будет происходить рендеринг информации об ошибках без подробного описания. Пример: ‘@yii/views/errorHandler/error.php’ |
$exceptionView | строка | Путь к файлу, в котором будет происходить рендеринг информации об исключениях. Пример: ‘@yii/views/errorHandler/exception.php’ |
$maxSourceLines | число | Максимальное число отображаемого исходного кода. |
$maxTraceSourceLines | число | Максимальное число отображаемого исходного трэйс-кода. |
$previousExceptionView | строка | Путь к файлу, в котором будет происходить рендеринг информации о предыдущем исключении. Пример: ‘@yii/views/errorHandler/previousException.php’ |
Прямой вызов errorActions
В общем, в случае возникновения серьёзной ошибки мы бы хотели показать пользователю подробную информацию в удобном для восприятия виде.
Как раз-таки это и происходит в экшене errorAction
класса errorHandler
. С этой точки мы и будем направлены на SiteController -> actionError:
1 |
return [ |
2 |
'components' => [ |
3 |
'errorHandler' => [ |
4 |
'errorAction' => 'site/error', |
5 |
],
|
6 |
]
|
7 |
];
|
Определим экшен error
в SiteController:
1 |
namespace app\controllers; |
2 |
|
3 |
use Yii; |
4 |
use yii\web\Controller; |
5 |
|
6 |
class SiteController extends Controller |
7 |
{
|
8 |
public function actions() |
9 |
{
|
10 |
return [ |
11 |
'error' => [ |
12 |
'class' => 'yii\web\ErrorAction', |
13 |
],
|
14 |
];
|
15 |
}
|
16 |
}
|
Вот так вот будет выглядеть обработка ошибки (ссылка на более подробную информацию):
1 |
public function actionError() |
2 |
{
|
3 |
$exception = Yii::$app->errorHandler->exception; |
4 |
if ($exception !== null) { |
5 |
return $this->render('error', ['exception' => $exception]); |
6 |
}
|
7 |
}
|
Также вы можете точно определить, возникла ли ошибка или в вашем приложении не существует запрашиваемого маршрута:
1 |
public function actionError() |
2 |
{
|
3 |
$exception = Yii::$app->errorHandler->exception; |
4 |
if ($exception instanceof \yii\web\NotFoundHttpException) { |
5 |
// all non existing controllers+actions will end up here
|
6 |
return $this->render('pnf'); // page not found |
7 |
} else { |
8 |
return $this->render('error', ['exception' => $exception]); |
9 |
}
|
10 |
}
|
Вот мой обработчик ошибки Page Not Found 404:
Никто не запрещает на странице описания ошибки оставить свои контакты или показать материалы схожие с пользовательским запросом. Все эти меры увеличивают шансы сохранить своё лицо перед пользователем.
Вот моя страница с отображением ошибки (конечно же над ней нужно ещё работать и работать):
Обработка исключений
Для обработки исключений можем воспользоваться PHP-шной конструкцией try catch. Давайте посмотрим пример в котором разделим число на ноль:
1 |
use Yii; |
2 |
use yii\base\ErrorException; |
3 |
|
4 |
...
|
5 |
|
6 |
try { |
7 |
10/0; |
8 |
} catch (ErrorException $e) { |
9 |
Yii::warning("Division by zero."); |
10 |
}
|
11 |
|
12 |
...
|
В блоке catch
запишем предупреждение в лог. В Yii есть несколько методов логирования:
- Yii::trace(): сообщение с куском кода. Обычно используется во время разработки.
- Yii::info(): информационное сообщение.
- Yii::warning(): предупреждение о каком-то событии.
- Yii::error(): сообщение о фатальной ошибке.
Если же вам не нужно записывать событие в лог, а просто перенаправить пользователя на страницу с информацией об ошибке, то этих строчек будет достаточно:
1 |
use yii\web\NotFoundHttpException; |
2 |
|
3 |
throw new NotFoundHttpException(); |
Вот пример в котором мы выбрасываем исключение с определённым HTTP кодом и специальным сообщением:
1 |
try { |
2 |
10/0; |
3 |
} catch (ErrorException $e) { |
4 |
throw new \yii\web\HttpException(451, |
5 |
'Tom McFarlin\'s humor is often lost on me
|
6 |
(and lots of people).'); |
7 |
}
|
А вот что в этом случае увидит пользователь:
О логировании в Yii
Все ошибки в Yii логируются в зависимости от того, как вы их организуете и настроите. Если данная тема вам интересна, то можете ознакомиться с другими моими уроками по Yii:
Заключение
Надеюсь, что мне удалось раскрыть тему, и должным образом показать процесс обработки ошибок и исключений. Следите за обновлениями серии Разработка на базе Yii2, где мы затрагиваем различные аспекты работы с фрэймворком.
Если же вы хотите более глубоко нырнуть в изучении Yii, то советую ознакомиться с серией по Созданию стартапа на PHP, где активно используется компонент шаблонизатора Yii2. В данной серии описаны все этапы создания сервиса Meeting Planner. Для тех кто только начинает учить Yii — данный материал будет очень полезен.
Если вы хотите первыми узнать о выходе новых уроков по Yii2 подписывайтесь на мой Twitter @lookahead_io и персональную страницу.
Похожие материалы
- Документация по yii\web\ErrorHandler
- Обработка ошибок (Руководство по Yii 2.0)
- Логирование (Руководство по Yii 2.0)
- Обмен опытом по работе с Yii2 (сайт автора)