Kohana: обработчик ошибок или собственная страница 404
Что произойдет в случае, когда пользователь запросит несуществующую страницу или в коде окажется ошибка?
Возникнет исключение, которое перехватит обработчик и отобразит на экране сообщение об ошибке вместе с кодом где она произошла. Это очень удобно при разработке, но неприемлемо на рабочем проекте.
Значит, нужно перехватить исключение до стандартного обработчика, проанализировать и отобразить либо собственную страницу ошибки (для рабочего проекта), либо стандартную страницу ошибки (для проекта в режиме разработки).
В Kohana исключения обрабатывает системный класс Kohana_Kohana_Exсeption
, который отображает страницу ошибки, используя представление system/views/kohana/error.php.
Создадим свой класс, унаследовав его от системного, и поместим в application/classes/kohana/exception.php:
class Kohana_Exception extends Kohana_Kohana_Exception {
public static function handler(Exception $e)
{
// Стандартная обработка, если проект на стадии разработки
if (Kohana::DEVELOPMENT === Kohana::$environment)
{
parent::handler($e);
}
else
{
try
{
// Пишем в лог
Kohana::$log->add(Log::ERROR, parent::text($e));
$attributes = array
(
'action' => 500, // Ошибка по умолчанию
'message' => rawurlencode($e->getMessage())
);
// Получаем код ошибки, как название экшена
if ($e instanceof HTTP_Exception)
{
$attributes['action'] = $e->getCode();
}
// Выполняем запрос, обращаясь к роутеру для обработки ошибок
echo Request::factory(Route::get('error')->uri($attributes))
->execute()
->send_headers()
->body();
}
catch (Exception $e)
{
// Чистим буфер и выводим текст ошибки
ob_get_level() and ob_clean();
echo parent::text($e);
exit(1);
}
}
}
}
Этот код содержит проверку состояния проекта. Если проект в состоянии Kohana::DEVELOPMENT
, то вызывается стандартный обработчик исключения. В противном случае – делается запись в лог с сообщением об ошибке и вызывается роутер Route::get(‘error’)->uri($attributes)
.
В Kohana может быть несколько состояний проекта:
Kohana::PRODUCTION
– готовый проект;Kohana::STAGING
– подготовка к релизу;Kohana::TESTING
– тестирование;Kohana::DEVELOPMENT
– разработка (по умолчанию).
Текущее состояние проекта хранится в Kohana::$environment
, определяется в bootstrap.php из переменной окружения $_SERVER['KOHANA_ENV']
, которую можно определить в файле .htaccess следующим образом:
SetEnv KOHANA_ENV testing
Определили проект, находящийся на тестировании.
Теперь нужно определить правило для роутера, который будет вызываться из нашего обработчика ошибок.
В bootstrap.php добавляем следующие строки:
Route::set('error', 'error/<action>(/<message>)', array('action' => '[0-9]++', 'message' => '.+'))
->defaults(array(
'controller' => 'error',
));
Следующим нашим действием будет создание контроллера Controller_Error
, который будет вызываться роутером. Для этого создаем файл controllers/error.php такого содержания:
class Controller_Error extends Controller_Template {
public $template = 'templates/error';
public function before()
{
parent::before();
// Получаем статус ошибки
$status = (int) $this->request->action();
// Получаем сообщение об ошибке
if (Request::$initial !== Request::$current)
{
$message = rawurldecode($this->request->param('message'));
if ($message)
{
$this->template->message = $message;
}
}
else
{
$this->request->action(404);
}
$this->response->status($status);
}
public function action_404()
{
$this->template->title = 'Запрашиваемая страница не найдена.';
}
public function action_503()
{
$this->template->title = 'Сервис временно недоступен.';
}
public function action_500()
{
$this->template->title = 'Внутренняя ошибка сервера.';
}
}
Для каждого кода ошибки в контроллере Controller_Error
используется свой action
, но View
используется один общий views/templates/error.php, в котором можно использовать переменные message
и title
.
Итого. Что у нас получилось: класс Kohana_Exeption
перехватывает исключение, проверяет переменную окружения, если статус не DEVELOPMENT, то обращается к роутеру error
, который вызывает соответствующий action
контроллера Controller_Error
(в зависимости от кода ошибки), и выводит результат используя views/templates/error.php.
(#) Ramka:
На версию 3.2.2 подошло. Все работоспособно. Спс.
(#) Сергей:
Отличная статья, Спасибо! (На 3.2.2 работает, подтверждаю)
(#) Alex:
А у меня не работает, так же продолжает выводить кохановский красный обработчик и там выкидывает 404 exception . Такое ощущение как буд то раут не срабатывает… что делать подскажите
(#) Alex:
Спасибо Дмитрию за помощь. Из за не внимательности exception.php прописал в
application/classes/controller/kohana/exception.php. Обратите на это внимание, нужно прописывать :
application/classes/kohana/exception.php не в контроллере а сразу в папке classes. Надеюсь поможет кому если столкнулся с такой же проблемой.
Ещё раз спасибо Дмитрий.
(#) dimka:
Всегда пожалуйста!
(#) ProGerome:
А на версию 3.3 подойдет? А то я попробовал, но перенаправления на контроллер ошибок не происходит.
(#) dimka:
Начиная с версии 3.3 все очень просто делается.
Читать здесь http://kohanaframework.org/3.3/guide/kohana/tutorials/error-pages