Роутинг — Часть 3

Комментарии: 84  Просмотры: 31 311

В этом уроке мы рассмотрим до конца основные возможности роутинга в Кохане. Ну а если вдруг что-то пропустим, изучим уже по мере надобности в последующих уроках.
В настройках роута, помимо указания в массиве таких параметров, как controller и action, есть возможность указывать директорию directory. Для чего это может понадобиться ? Самый типичный пример — это раздел администратора. Довольно часто он прилично отличается по своей структуре от основного сайта, поэтому обычно его Контроллеры выносят в отдельную директорию. Вот эту самую директорию мы в роуте и пропишем. Делается это легко. В массиве появляется новый параметр directory:

Route::set('admin', 'admin(/<controller>(/<action>(/<id>)))')
            ->defaults(array(
            'directory'  => 'admin',
            'controller' => 'main',
            'action'     => 'index',
            ));

Теперь нужно создать файл Контроллера main.php и поместить его в директорию application/classes/controller/admin/. Контроллер будет очень простым:

<?php defined('SYSPATH') or die('No direct script access.');
 
class Controller_Admin_Main extends Controller_Common {
 
    // Главная страница
    public function action_index()
    {
        $content = View::factory('/admin/show');
        $this->template->content = $content;
    }
 
} // End Main

Здесь только два нюанса.
1. Поскольку Контроллер находится внутри директории admin, то название класса будет не Controller_Main, а Controller_Admin_Main. О формировании названий классов я неоднократно говорил и еще раз на всякий случай напоминаю.
2. У админки скорее всего будет свой собственный базовый Контроллер. Но здесь, для упрощения, я унаследовал класс Controller_Common. Просто имейте ввиду.
Ну и наконец последнее, что нужно сделать — это создать шаблон админки. Лежать он будет в application/views/admin/ и называться show.php. Не будем мучиться и придумывать что-то сложное, это вы сделаете сами. Я просто поместил туда текст:

<h3>Это админка</h3>

И теперь, если вы перейдете по адресу http://kohana/admin, то увидите свою админку во всей ее красе.
Для директорий также можно указать регулярное выражение, как мы это делали с action для страниц «О сайте» и «Мои контакты». Приведу пример из официального мануала фреймворка:

Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))', array('directory' => '(admin|affiliate)'))    
        ->defaults(array(        
            'controller' => 'home',        
            'action'    => 'index',    
        ));

Как это работает, должно быть понятно. Если кому-то непонятно, добро пожаловать в комментарии.
Идем дальше. Иногда нам нужно знать, какой Контроллер или action-метод отработал в данный момент. И очень часто нам нужно получить значения каких-то параметров, переданных в адресной строке. Немного я об этом уже говорил в предыдущих уроках, ну а теперь подробно.
Названия текущей директории, контроллера и action-метода можно получить следующим образом.
В контроллере:

$this->request->directory();
$this->request->controller();
$this->request->action();

Где угодно:

Request::current()->directory();
Request::current()->controller();
Request::current()->action();

Все остальные параметры (такие как id1, id2 итд) можно получить следующим образом:
В контроллере:

$this->request->param('id');

Где угодно:

Request::current()->param('id');

Понятно, что здесь в скобках указывается название нужного нам параметра. И это необязательно будет id.
Теперь, если мы исправим наш админский шаблон на такой:

<h3>Это админка</h3>
Директория  - <?php echo Request::current()->directory(); ?><br /><br />
Контроллер - <?php echo Request::current()->controller(); ?><br /><br />
Метод - <?php echo Request::current()->action(); ?>

То в админке получим:
Это админка
Директория — admin
Контроллер — main
Метод — index

Раз уж мы заговорили о параметрах, просто чтобы вы знали, их можно получать и в качестве аргументов метода, но лучше так не делать (Дополнение: как выяснилось, в версии 3.2 этого все-таки нельзя уже делать. Убрали и правильно сделали).
Теперь давайте поговорим про формирование адресов вида http://kohana/article1.html. Думаю вы не раз видели такие адреса. На первый взгляд можно подумать, что сайт полностью сделан из статических html-страниц. В Кохане все это реализовывается также через роуты.
Опять возьму пример из официального мануала:

Route::set('static', '<path>.html',  array('path' => '[a-zA-Z0-9_/]+',))  
        ->defaults(array(
            'controller' => 'static',    
            'action' => 'index',  
        ));

У нас метода action_index в Контроллере static нет, но вы можете создать его, прописав внутри что-то вроде:

echo $this->request->param('path');

и тогда уже по адресу http://kohana/article1.html вы получите свой article1.
Ну и напоследок хотелось бы сказать про метод get. Если уже знакомый нам метод set устанавливает маршрут, то метод get, наоборот, получает маршрут. Выглядит это как-то так:

Route::get('default')->uri(array(
            'controller' => 'test',
            'action'    => 'index',
        ));

Если засунуть этот код внутрь контроллера и вывести через echo, то мы получим адрес test/index. А если написать:

Route::get('admin')->uri(array(
            'controller' => 'test',
            'action'    => 'index',
        ));

И вывести, то получится уже admin/test/index. Таким образом формируется нужный URL, согласно маршрутам, прописаным в соответствующих роутах. Возникает закономерный вопрос, а для чего это может нам понадобится. Если честно, я данный метод еще ни разу не использовал. Но это может пригодится для формирования ссылок в проекте. Тогда при каких-то изменениях, касающихся ваших ссылок (например, при замене косой черты на подчеркивание), вам не нужно будет их править, они изменятся по всему сайту автоматически.
А теперь совсем напоследок расскажу о кешировании роутов. Как вы успели заметить, хотя мы только начали создавать что-то вроде блога, но различных роутов накопилось уже приличное количество. Естественно каждый раз при загрузке сайта происходит обработка всех этих роутов, что довольно ресурсоемко, особенно если их много. Поэтому, когда разработка сайта завершена и роуты уже изменяться не будут, их обычно кешируют. У класса Route есть метод Cache, который принимает булево значение TRUE или FALSE. Я не устану повторять, что Кохана очень хорошо самозадокументирована, поэтому если вы не поленитесь и найдете в файле system/classes/kohana/route.php этот метод, то в комментариях увидите подробное (но на английском) его описание:

   /**
    * Saves or loads the route cache. If your routes will remain the same for
    * a long period of time, use this to reload the routes from the cache
    * rather than redefining them on every page load.
    *
    *     if ( ! Route::cache())
    *     {
    *         // Set routes here
    *         Route::cache(TRUE);
    *     }
    *    ...
    */

То есть все, что нужно сделать — это поместить наши роуты внутрь этого условия (вместо текста «//Set routes here»). Если вы все сделали правильно, то после открытия любой страницы сайта вы увидите сгенерированный кеш в папке application/cache/.
Ну теперь окончательно все. Довольно длинный урок получился. Это в качестве компенсации, что долго ничего не выкладывал :) Всех с наступающим. Встретимся в 2012 году.

<< Назад | Вперед >> | Обсудить на форуме


К записи оставлено 84 коммент.

Может у меня порядок роутов не верный в bootstrap? Подскажите где может быть ошибка?
Вроде все как по уроку:
Route::set(‘admin’, ‘(/(/(/)))’,array (‘directory’=>’admin|affilate’))
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘main’,
‘action’ => ‘index’,
));

Route::set(‘static’, ‘.html’, array(‘path’ => ‘[a-zA-Z0-9_/]+’,))
->defaults(array(
‘controller’ => ‘static’,
‘action’ => ‘index’,
));

Route::set(‘static’, ‘(/)’,array(‘action’=>’about|contacts’))
->defaults(array(
‘controller’ => ‘static’,
));

Route::set(‘articles’, ‘(/)’, array(‘id’ => ‘.+’))
->defaults(array(
‘controller’ => ‘articles’,
‘action’ => ‘index’,
));

Route::get(‘admin’)->uri(array(
‘controller’ => ‘page’,
‘action’ => ‘index’,
));

Route::set(‘default’, ‘((/(/)))’)
->defaults(array(
‘controller’ => ‘page’,
‘action’ => ‘index’,
));

Денис, наверное стоит добавить небольшую оговорку в этот урок по роутингу. В данный момент текущая стабильная версия kohana 3.3.
В ней появились немного иные правила именования папок и классов в разделе application/classes. Все папки и файлы должны начинаться с заглавной буквы.
Т.е. например ваш путь application/classes/controller/admin/ для версии 3.3 должен выглядеть так application/classes/Сontroller/Аdmin/ и сам файл main.php должен быть называн Main.php.
Если оставить первую букву в нижнем регистре — кохана на отрез отказывается подгружать нужные классы и выдает 404 страницу. Потратил час времени на решение. Я думаю новичков стоит предупредить о такой возможности.
Оговорюсь, вероятно такая проблема может возникнуть только у линукс пользователей.

у меня версия 3.3 і все с большой букви так как Ви говорите. і в bootstrap’e
Kohana::init(array(
‘base_url’ => ‘/’, ‘index_file’ => FALSE
));
но все равно такой адрес http://kohana/about видает 404
а такой работает корректно http://kohana/index.php/about

example.htaccess тоже переименовали ?

да. все как написано

решил подобную проблему, заменив в .htaccess
строку
RewriteRule .* index.php/$0 [PT]
на
RewriteRule .* index.php [PT]

не выходит зайти в админку, пишет
ErrorException [ Parse Error ]: syntax error, unexpected T_STRING

в строке
php defined(‘SYSPATH’) or die(‘No direct script access.’);

все пути вроде правильно написал, файлы в нужных папках

Здравствуйте.
Стоит задача перенести сайт на Кохану 3.3.1
Нужно сохранить старые ссылки вида mysite.ru/blog/24-nazvanie-stati.html

Пытаюсь сделать роутер на вашем примере

Route::set('static', '(/).hmtl', array('action' => 'about|contacts'))
        ->defaults(array(
            'controller' => 'Static',
            'action' => 'index',
    ));

Но к сожалению параметр action, когда в роутер приходит например about.html все равно остается дефолтным index
Подскажите, что я не так делаю

Всем здравия, вопрос к знатокам. Роутинг в под-каталог контролера, нет конекта.

Kohana_HTTP_Exception [ 404 ]: The requested URL admin/panel/5 was not found on this server.

Сил уже нет около 5 часов ламаю голову, огромное количество страниц с аналогичными проблемами пересмотрел, не решаеться. Подозриваю что из-за OS

KOHANA 3.3.1 PHP 5.4.9 Apache/2.2.22 OS Linux

.htaccess подключен, настроен

Controller —————————————————
test.loc/public/kohana/application/classes/Controller/Admin/Panel.php

class Controller_Admin_Panel extends Controller {

public function action_index()
{
echo «Controller_Admin_Panel»;
}

} // End class Controller_Admin_Panel

Имена каталога Admin, файла Panel.php и на сервере и в коде прописывал в разных регистрах первый символ.

Bootstrap.php ————————————————

Kohana::init(array(
‘base_url’ => ‘/kohana/’,
‘index_file’ => false
));

Некоторые вырианты что перепробывал (код не однократно изминял):

Route::set(‘admin’, ‘admin(/(/(/)))’)
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘main’,
‘action’ => ‘index’,
));

Route::set(‘admin’, ‘admin(/(/(/)))’)
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘main’,
‘action’ => ‘index’,
));

$route = Route::set(‘forum’, ‘()(/)(()(/)(/page))’, array
(
‘controller’ => ‘[a-z]+’,
‘id’ => ‘[0-9]+’,
‘page’ => ‘[0-9]+’,
‘action’ => ‘[\pL]+’,
‘directory’ => ‘forum(/admin){0,1}’
))
-> defaults(…);

Route::set(‘admin’, ‘admin/((/(/)))’)
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘main’,
‘action’ => ‘index’,
));

Route::set(‘admin-author’, ‘(/(/(/)))’, array(
‘directory’ => ‘(admin|admin/author)’,
‘action’ => ‘(add|edit|delete|index)’
))
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘author’,
));

Route::set(‘admin’, URL::base().’admin(/(/(/)))’)
->defaults(array(
‘directory’ => ‘admin’,
‘controller’ => ‘Main’,
‘action’ => ‘index’,
));

// Admin routes
Route::set(‘admin’, ‘(/(/(/)))’,
array(
‘directory’ => ‘admin’
))
->defaults(array(
‘controller’ => ‘Panel’,
‘action’ => ‘index’,
‘directory’ => ‘admin’,
));

Route::set(‘admin’, ‘Admin(/(/(/(/))))’)
->defaults(array(
‘directory’ => ‘Admin’,
‘controller’ => ‘panel’,
‘action’ => ‘index’,
));

Route::set(‘post’, ‘admin/(/)/’)
->defaults(array(
‘directory’ => ‘admin’,
‘action’ => ‘index’,
));

Route::set(‘something’, ‘admin(/(/(/(/))))’)
->defaults(array(
‘directory’ => ‘Admin’,
‘controller’ => ‘Panel’,
‘action’ => ‘index’,
));

Официальную документацию на изусть выучил…про всех примерах что находил проходился… нифига не врубаюсь в чем засада. Гдето какуюто малую деталь упускаю… если это не из-за сервера на линуксе.

Человеки кто работает некоторое время. есть идеи

Проблема с сервером LAMP на lubuntu. На Винде лок-сервер Open Server роуты работают.

«То есть все, что нужно сделать — это поместить наши роуты внутрь этого условия (вместо текста «//Set routes here»). Если вы все сделали правильно, то после открытия любой страницы сайта вы увидите сгенерированный кеш в папке application/cache/»
Не понял где нужно вставлять — прямо по пути в system/classes/kohana/route.php? Так вроде в system договорились не влазить. А в application такого пути вообще нет?

«прямо по пути в system/classes/kohana/route.php» — выдаёт 500 ошибку…

Здравствуйте, а вот если у меня контроллер находится в поддиректории «admin» как я могу к нему обратится с адресной строки — без использование Роутов???

Полный путь: «application\classes\Controller\admin\User.php»

Как это ? Напрямую ? Он у вас независимый и не использует никаких библиотек ?

Немного не правильно выразился.

Я делаю вот так:

Route::set('admin', 'admin/((/))')
	->defaults(array(
                   'directory' => 'admin',
                   'controller' => 'User',
		   'action'     => 'index'
	));

По этим ссылкам все работает:
1. http://cms.ua/admin/user
2. http://cms.ua/admin/user/delete
3. http://cms.ua/admin/user/edit

А вот по этой этой кричит 404:
http://cms.ua/admin

Хотя вроде как должно работать. Поскольку контроллер и скрипт указан как не обязательный. А в дефолтных все установлено и директория и контроллер, скрипт.

Подскажите пожалуйста в чем я неправ? И поправьте мой роут — для примера, пожалуйста. Заранее очень благодарен.

Route::set('admin', 'admin(/(/<action>))', array('action' => '.+'))
	->defaults(array(
            'directory'  => 'admin',
            'controller' => 'User',
            'action'     => 'index',
	));

Денис Васильевич, спасибо вам огромное — работает. :-)

Только вот совсем не могу понять третий параметр
array(‘action’ => ‘.+’)), зачем он и что значит ‘.+’???

значит, что action может принимать любые символы. Регулярка обычная (регулярное выражение).

Еще раз спасибо огромное :-)

Доброго времени суток, собираюсь перевести один рабочий проект на kohana и стоит задача сохранить ссылки. Не могу вот построить правильный route, может кто подскажет:

site.name/catalog/category/param1/value1/param2/value2/param…/value…/param_n/value_n

Кто подскажет?



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

Пожалуйста, зарегистрируйтесь для комментирования.