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

Комментарии: 56  Просмотры: 49 946

Вот мы и дошли до очень важной темы — темы Роутинга в Кохане. Хочу поблагодарить Семёна c phpforum.ru за разъяснение некоторых нюансов в этой достаточно сложной теме. Теперь можно приступать.
Роутинг — это процесс определения маршрута внутри нашего приложения после поступления запроса. Т.е. после того, как мы переходим по ссылке в адресной строке, происходит ее обработка, согласно определенным правилам. Мы с вами уже немного работали с роутами, когда прописывали свой Контроллер Page вместо Контроллера Welcome. И даже добавляли в него свои методы (кто забыл, смотрите урок Заготовка для блога — Часть1). Таким образом при переходе по ссылке http://kohana у нас вызывался Контроллер Page и метод index, а вот для вызова методов about и contacts нужно было уже писать http://kohana/page/about и http://kohana/page/contacts, т.е. название Контроллера, а потом название метода. Это не очень красиво. Но если написать в адресной строке http://kohana/about, то вместо нашей страницы «О сайте» мы все равно получим главную страницу. Еще надо отметить, что как-то не очень хорошо, когда все страницы лежат в одном Контроллере, тем более такие. Все-таки основная страница — это основная страница. Там будут выводиться статьи и всяческая динамическая информация вроде количества просмотров, количества комментариев и так далее. А страницы «О сайте» и «Контакты» — это статика, обычно их один раз написали и все. Давайте вынесем их в отдельный Контроллер. Для этого в папке с двумя нашими Контроллерами создадим еще один с названием static.php и со следующим кодом (я скопировал его из Контроллера Page, а там удалил):

<?php defined('SYSPATH') or die('No direct script access.');
 
class Controller_Static extends Controller_Common {
 
    // Страница о сайте
    public function action_about()
    {
        $content = View::factory('/pages/about');
        $this->template->content = $content;
    }
 
    // Страница контактов    
    public function action_contacts()
    {
        $content = View::factory('/pages/contacts');
        $this->template->content = $content;
    }	
 
} // End Static

В этом Контроллере пусть у нас будут такие вот статичные страницы (О сайте, Контакты, FAQ, Правила, Друзья итд). В принципе мы уже можем работать с этими страницами. Если доступ к главной странице таким же и остался — через http://kohana или http://kohana/page, то для этих страниц ссылки будут http://kohana/static/about и http://kohana/static/contacts. То есть сменили «шило на мыло». Было page, стало static. Как избавиться от сегмента static ? В этом нам помогут роуты. Для начала давайте рассмотрим структуру роута на примере роута по умолчанию (находится в файле bootstrap.php в самом низу).

Route::set('default', '(<controller>(/<action>(/<id>)))')
	->defaults(array(
            'controller' => 'page',
            'action'     => 'index',
	));

Здесь мы видим статический метод set, которому передаются два параметра. Первый параметр — это название данного роута. Второй — какое-то правило. На самом деле есть еще третий параметр, который используется по необходимости — это регулярное выражение. С первым параметром все ясно. Второй параметр выглядит у нас так:

(<controller>(/<action>(/<id>)))

Косая черта служит для разделения сегментов адреса друг от друга (в принципе вместо косой черты можно сделать что-то другое, подчеркивание например). Угловые скобки <> указывают, что то, что попадет в них, будет присвоено переменной с именем внутри этих скобок (если этот момент пока непонятен, не волнуйтесь, позже я покажу это на примере). Этих скобок может и не быть, если требуется, чтобы сегмент адреса четко совпадал с роутом (это мы рассмотрим чуть ниже). Круглые скобки означают, что данный параметр необязателен. Т.е. он может быть, а может и не быть. Вы можете сами это проверить. Главная страница будет работать по такому адресу http://kohana/page/index и по такому http://kohana/page и даже по такому http://kohana. Следовательно, чтобы сделать указание Контроллера обязательным, второй параметр нужно изменить на такой:

<controller>(/<action>(/<id>))

Естественно, необходимо соблюдать вложенность скобок. Не может быть, например, необязательный Контроллер, но обязательный Id. Думаю с этим все понятно.
Как Кохана определяет, какой Контроллер вызывать, если мы не указали его в адресной строке, например перешли по адресу http://kohana. Для этого у роута есть функция defaults, в которую передается некий массив параметров в виде ключ — значение, где ключом будет название параметра, а значением, как ни странно, его значение. Нам пока достаточно знать два параметра. Это controller — принимающий название Контроллера, который будет запущен и action — название метода этого Контроллера. Вот мы и написали туда наш Контроллер page и наш метод index, которые собственно и срабатывают. Но вернемся к нашей задачке со статическими страницами. Одним из вариантов ее решения будет два новых роута:

Route::set('about', 'about')
	->defaults(array(
            'controller' => 'static',
            'action'     => 'about',
	)); 
 
Route::set('contacts', 'contacts')
	->defaults(array(
            'controller' => 'static',
            'action'     => 'contacts',
	));

Попробуйте зайти на http://kohana/about или http://kohana/contacts. Все должно работать (не забудьте поправить ссылки в шаблоне). Получается, что когда вы переходите по ссылке http://kohana/about, то сегмент с about попадает под правило первого роута, поэтому вызывается Контроллер static и Метод about. Со второй ссылкой аналогично, только теперь уже срабатывает второй роут.
Обратите внимание, угловые скобки мы не использовали. Т.е. нам нужно именно четкое совпадение или с about, или с contacts. Если все же использовать угловые скобки, то мы все время будем попадать на страницу «О сайте», причем даже при вводе таких адресов как http://kohana/faq так как будет выполняться первый же роут, как соответствующий условию. Просто в параметр about попадет слово «faq», которое потом можно получить например в Базовом Контроллере.
В следующем уроке мы перепишем этот пример с использованием регулярного выражения и обойдемся одним роутом вместо двух, а также создадим еще несколько роутов для понимания (или закрепления) материала из этого урока.

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


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

Наконец-то!!!
Земной поклон вам добрые люди!)
С нетерпением жду следующих уроков.

Хотелось бы сказать всем. Если вам нравится ресурс, был бы очень рад, если бы вы разместили ссылочку на него у себя на сайте или например порекомендовали его на форуме по программированию, где вы бываете (только пожалуйста без спама). Больше ссылок — сильнее «любят» поисковики. Может получится хоть какой-то доход с рекламы, да и мне стимул почаще выпускать уроки :)

Денис, так а вы сочините кнопку с кодом чтобы копипаст и все)

сделал кнопку. смотрите на главной :)

Все это хорошо, но как по мне это не совсем удачный способ делать статические страницы.
Лучше создать общий контроллер который будет тянуть с базы статические страницы. Надеюсь понятно что при этом чтобы узнать какую нам нужно взять страницу просто передаем параметром в адресной строке.

Ну вот мы и создали общий контроллер для статических страниц. А до базы мы еще не добрались. В любом случае, я не считаю рентабельным использовать базу данных для статических страниц, если мы знаем сколько их будет и какие они. Можно вообще все в базу засунуть, как в этом вордпрессе, только вот ложится он при мало-мальски приличной нагрузке.

Ну скорее мой вариант подходит для людей которые будут работать исключительно с админкой, а не с кодом.

Ну да. Это все уже нюансы работы, зависящие от условий. Моя задача — рассказать про сам фреймворк. А как этим пользоваться-уже решать вам.

Извиняюсь, но с правилом ((/(/))) что-то не ясно… почему в роуте мы его не используем, а пишем просто ‘about’ или ‘static’? почему не написать так:

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

и вот тут: ‘Просто в параметр about попадет слово «faq», которое потом можно получить например в Базовом Контроллере.’

что-то недопонял… как это слово попадает в параметр?

извиняюсь, если туплю.

Фильтр обрезал часть кода, попробую догадаться :)
Так писать можно, но тогда на about мы напишем как у вас, на faq тоже прийдется писать, только поменяется ‘action’ => ‘faq’. Будет еще какая-то статичная страница, еще один роут прийдется создавать. А так все в одном. Появилась новая страница, в регулярку слово добавили и все. В action оно автоматом подставится.

Упс. походу я не то ответил. Я думал это к уроку Роутинг Часть-3. Там мы регулярку уже применяем.
Вообщем еще раз напишите код. Только поместите его в теги

<pre lang="php">
Route::set('sections', '<directory>(/<controller>(/<action>(/<id>)))', 
array('directory' => '(admin|affiliate)'))

Уже вкурил сам. Как и предполагалось, — тупил. Во второй части Вы все разъяснили.

А вопрос был таким: зачем прописывать роуты для каждой статической страницы, когда можно прописать общее правило.

Route::set('sections', '(/(/(/)))', 
array('directory' =&gt; '(page_0|page_1)'))

что-то не прописывается правило )))
да и бес с ним, проехали )

Ну да. Я как бы плавно к этому подвел. Сначала показал на двух роутах, потом вариант получше :)

Здравствуйте.
Очень понравились ваши уроки, сам я из начинающих, давно пытался освоить Kohana но везде так заумно объясняют что после первых строк дальше и заниматься не хочется а у вас все просто и доходчиво.
Вот по этому уроку, как нужно настроить денвер чтобы роуты срабатывали, у меня в любом варианте выдает ошибку.Если это ((/(/))) меняю на это (/(/)) то вообще главная не грузится.

Не видно кода. Обрамляйте код тегами pre. Или пишите на форуме, поможем.

Помогите, пожалуйста, разобраться с проблемой.
Ввожу http://kohana/about, получаю
HTTP_Exception_404 [ 404 ]: The requested URL вып was not found on this server.
SYSPATH\classes\kohana\request\client\internal.php [ 87 ]
Это ещё до редактирования роутинга, описнного в данном уроке.
Пару дней назад впервые поставил Кохану и прошёл все этапы — проблема была аналогичная. Предположил, что я где-то напутал, решил взять, и проделать всё с нуля. Проделал всё с нуля — проблема осталась.
Грубо говоря, она заключается в том, что любая ссылка, кроме реально существующей, выдаёт сообщение об ошибке парсера. Вы же говорите о том, что должен выдаваться редирект на главную. Это не так и принципиально до момента, описанного в следующем уроке, когда идёт описание работы с articles.
Всё проделываю на Denwer, все шаги дословно повторил с первого урока, релиз качал с офф. сайта. В чём может быть проблема?

свои Роуты пишите перед основным.

Route::set('about', 'about')
    ->defaults(array(
	     'controller' => 'static',
		 'action' => 'about',
    ));

Route::set('contacts', 'contacts')
    ->defaults(array(
	    'controller' => 'static',
		'action' => 'contacts',
	));	   

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

архитектура такая.
если иначе то будут ошибки т.к. сначала будет идти Роут по умолчанию, а он всегда верный.
и все что ниже него просто игнорируется.
если не верно поправьте, я недано изучаю php и с ООП практически не знаком.
но именно так я избавился от такой ошибки.

В первом примере кода, где Controller_Static, заменить последнюю строчку
} // End Page
на
} // End Static

А так — всё отлично. Спасибо

Поменял, благодарю. Приятно, когда люди внимательно читают и вникают, а не копипастят код 1 в 1.

Здравствуйте!
К сожалению с данного урока я так и не понял, — какой же все-таки код должен остаться в Controller_Static и какой в Controller_Page?
Все начиналось так хорошо, — понятно..!
Но почему-то в один момент, — раз и все..»Для этого в папке с двумя нашими Контроллерами создадим еще один с названием static.php и со следующим кодом (я скопировал его из Контроллера Page, а там удалил):»
Что удалил, — все, что там было или как..? А что осталось? Или как изменилось?
Вы уж, пожалуйста, пропишите все четко, — что удалилось и где, и что осталось, так же где! И самое главное, — как это должно выгладить.
Ведь, Вы же делаете урок для начинающих..!!!!
А такие провалы подойдут только для уже искушённых товарищей в CMS Kohana.!
Вы хорошо рассказываете, но вот такие провалы ставят людей в тупик, по этому и много комментов к каждому уроку, к сожалению..! Потому, как многое не понятно.

Я смотрю, у Вас в ссылках мелькает Е.Попов, — у него таких провалов в объяснениях практически нет. Я начинал с чистого листа с его уроков и видеоуроков, — молодцом парень, честь и хвала!!!

Если можно, то пропишите более точно, что, куда, где, когда и почему. А самое главное, — как это будет выглядеть в окончательном варианте!

С Уважением, msgraf!

Код, как выглядит Controller_Static есть здесь в самом верху:
http://kohanaframework.su/starting/blog_p1
В нем три метода: action_index(), action_about() и action_contacts(). Соответственно если мы «создадим еще один с названием static.php и со следующим кодом (я скопировал его из Контроллера Page, а там удалил)», а следующий код — это два метода action_about() и action_contacts(), то в Controller_Static мы их удаляем и там останется только action_index(). Куда уж проще ?
Старайтесь вникать в текст, а не только копировать код. А то тут было, когда я, чтобы не копировать весь код, который был рассмотрен в предыдущем уроке, поставил многоточие. Так люди вместе с многоточием копировали и еще удивлялись, почему в этой строке ошибка.

Поправлюсь.
Я все это написал не потому, что есть желание скопировать 1 к 1-му, потому, что бы разобраться в мелочах.
А как мы все понимаем, — это и есть суть Ваших уроков…, или я не прав?!

Tще раз, с Уважением, msgraf!

Тут главное не разобраться, какой код мы куда копируем, а понять, для чего это делается. В данном случае мы разделяем контроллер на два, чтобы один отвечал за статичные страницы (контакты и о сайте), а другой за динамические.



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

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