Это статья для тех, использует Kohana Framework.
Заметил в последнее время много вопросов по поводу того, как сделать свою собственную страницы 404 на Kohana Framework, да и вообще, как правильно работать с исключениями и обрабатывать сообщения об ошибках.
Что сделает Kohana, если пользователь, к примеру, запросит страницу, которая не существует?
По умолчанию выведет сообщение об ошибке, так как сработает исключение. Да и не просто выведет сообщение, но и покажет часть кода, где у вас произошла ошибка. Это конечно хорошо, но только на этапе разработки. Вряд ли захочется показывать такое пользователю. Надеюсь все согласны?
Конечно, можно просто делать редирект, если какой-то страницы уже не существует, но согласитесь, это не лучшее решение. Есть еще пару кривых способов, но самое правильное решение – перехватывать исключения и обрабатывать их, при этом в зависимости от возвращаемого кода ошибки (404 File Not Found, 403 Forbidden и т.п. ) иметь возможность выводить свое представление (View).
По умолчанию в Kohana есть класс Kohana_Kohana_Exсeption, который обрабатывает все типы исключений одинаково, используя одно лишь представление (system/views/kohana/error.php) . Но ничто нам не мешает создать свой класс обработки исключений, унаследовав его от системного, и заложить свою логику.
Начнем. Обратите внимание, что я буду рассказывать на примере Kohana Framework версии 3.2. Это принципиально, потому что в разной версии это делается немного по разному, хотя общий принцип схож.
Шаг 1. Создать класс 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);
}
}
}
}
Комментарии в коде. Обратите внимание, что в самом начале есть проверка:
Код:
if (Kohana::DEVELOPMENT === Kohana::$environment)
В Кохане существует несколько состояний проекта для удобства.
Kohana::PRODUCTION – готовый проект
Kohana::STAGING – подготовка к релизу
Kohana::TESTING – тестирование
Kohana::DEVELOPMENT – разработка (по умолчанию)
Это просто константы. Например, мы можем установить текущее состояние проекта на PRODUCTION и только в этом случае обрабатывать исключения по-своему. Если же стадия DEVELOPMENT, то нам просто необходимо видеть, где у нас ошибки в проекте, это помогает при разработке.
Давайте так и сделаем. Как же установить текущее состояние проекта? Если заглянуть в bootstrap.php, то можно увидеть следующее:
Код:
if (isset($_SERVER['KOHANA_ENV']))
{
Kohana::$environment = constant('Kohana::'.strtoupper($_SERVER['KOHANA_ENV']));
}
Здесь мы видим, что текущее состояние проекта, то есть Kohana::$environment, берется из переменной окружения $_SERVER['KOHANA_ENV'], которую можно определить в файле .htaccess вот так:
SetEnv KOHANA_ENV production
Теперь у нас проект на последней стадии готовности.
Шаг 2. Создать контроллер controllers/error.phpКод:
class Controller_Error extends Controller_Template {
public $template;
public function before()
{
parent::before();
// Получаем статус ошибки
$status = (int) $this->request->action();
// Назначаем шаблон
$this->template = View::factory('errors/' . $status);
// Получаем сообщение об ошибке
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 = 'File Not Found';
}
public function action_503()
{
$this->template->title = 'Service Temporarily Unavailable';
}
public function action_500()
{
$this->template->title = 'Internal Server Error';
}
}
Как вы видите, для каждого кода ошибки мы можем создать свой экшен и обрабатывать, как душе угодно.
Шаг 4. Создать View для экшеновviews/errors/404.php
views/errors/403.php
views/errors/500.php
В этих вьюшках можно в данном случае использовать переменные title и message(сообщение об ошибке). Все это делается, конечно же, в папке с проектом application.
Шаг 3. А про роутер-то забыли!Наш класс Kohana_Exception будет обращаться к роутеру Route::get(‘error’)->…
Хм…а его и нет. Давайте исправим эту оплошность:
Создаем роутер в bootstrap.php
Код:
Route::set('error', 'error/<action>(/<message>)', array('action' => '[0-9]++', 'message' => '.+'))
->defaults(array(
'controller' => 'error',
));
Вот и все, поздравляю!
Теперь, чтобы вызвать сообщение об ошибке, в нужном месте выкидываем исключение:
Код:
throw new HTTP_Exception_404('Страница не найдена'); // Тададам!
или с передачей параметров:
Код:
throw new HTTP_Exception_404('Страница ":page" не найдена', array(':page' => 'Название страницы'));
Как это работает?Класс Kohana_Exeption отлавливает исключение, проверяет переменную окружения, если не DEVELOPMENT, то обращается к роутеру error, который вызывает соответствующий экшен контроллера Controller_Error (в зависимости от кода ошибки) и выводит результат.
Источник:
Школа программирования