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.


Комментарии

  1. (#)   Ramka:

    На версию 3.2.2 подошло. Все работоспособно. Спс.


  2. (#)   Сергей:

    Отличная статья, Спасибо! (На 3.2.2 работает, подтверждаю)


  3. (#)   Alex:

    А у меня не работает, так же продолжает выводить кохановский красный обработчик и там выкидывает 404 exception . Такое ощущение как буд то раут не срабатывает… что делать подскажите


  4. (#)   Alex:

    Спасибо Дмитрию за помощь. Из за не внимательности exception.php прописал в
    application/classes/controller/kohana/exception.php. Обратите на это внимание, нужно прописывать :
    application/classes/kohana/exception.php не в контроллере а сразу в папке classes. Надеюсь поможет кому если столкнулся с такой же проблемой.
    Ещё раз спасибо Дмитрий.


  5. (#)   dimka:

    Всегда пожалуйста!


  6. (#)   ProGerome:

    А на версию 3.3 подойдет? А то я попробовал, но перенаправления на контроллер ошибок не происходит.


  7. (#)   dimka:

    Начиная с версии 3.3 все очень просто делается.

    Читать здесь http://kohanaframework.org/3.3/guide/kohana/tutorials/error-pages


Оставить комментарий

Ответ на Kohana: обработчик ошибок или собственная страница 404