Как вы помните (еще об этом написано на главной странице), фреймворк Kohana использует архитектурную модель HMVC (Hierarchical Model View Controller — Иерарархические Модель-Контроллер-Вид). Но до текущего момента мы использовали только MVC, точнее даже VC (не путать с WC), так как до модели мы еще не добрались. HMVC — это развитие концепции MVC. Рисунок, представленный ниже, отображает принцип ее работы:
Совокупность Модель-Вид-Контроллер называется Триадой. Каждая триада функционирует независимо от других. Триада может запросить доступ к другой триаде через контроллер. Использование триад MVC позволяет добиться более глубокой и тщательной разработки приложений. Также уменьшается зависимость между различными частями приложения.
Давайте рассмотрим удобство такого подхода на примере комментариев к статьям. Как вы помните, у нас по адресу http://kohana/articles/article1 находится статья, название которой (для поиска по базе) — article1. Естественно комментарии уникальны, хранятся в базе данных и привязаны к конкретной статье. Мы работу с базой данных в Кохане еще не проходили, поэтому позже заэмулируем эту ситуацию. Но давайте обо всем по порядку. Измените Контроллер articles.php следующим образом:
<?php defined('SYSPATH') or die('No direct script access.'); class Controller_Articles extends Controller_Common { public function action_index() { $id = $this->request->param('id'); if($id) { $content = View::factory('/pages/article') ->set('article', $id) ->bind('comments', $comments); $comments_url = 'comments/' . $id; $comments = Request::factory($comments_url)->execute(); } else { $content = View::factory('/pages/articles'); } $this->template->content = $content; } } // Articles
Здесь я поменял блок, где выводится одна статья. Добавилась переменная $comments, которую мы передаем в блок с контентом. В ней собственно и будут лежать комментарии к статье. Откуда они там берутся ? Мы получаем их из специального Контроллера, сделанного под комментарии. Контроллер этот вызывается по адресу http://kohana/comments/наша статья, т.е. для адреса http://kohana/articles/article1 комментарии находяться по адресу http://kohana/comments/article1 (этот адрес собственно и присваивается переменной $comments_url). Логично, что раз у нас появился новый адрес, значит нужен новый роут. Поэтому в файле bootstrap.php добавьте следующие строчки (только добавляйте над роутами, относящимися к articles, в силу их «универсальности»:
Route::set('comments', 'comments/<id>', array('id' => '.+')) ->defaults(array( 'controller' => 'comments', 'action' => 'index', ));
Вот теперь, если обратиться по адресу http://kohana/comments/article1, у нас будет грузиться Контроллер из файла comments.php (на самом деле он пока у меня только будет грузится, у вас нет, так как вы его еще не сделали ). Грузиться он будет посредством строки:
$comments = Request::factory($comments_url)->execute();
Она как раз и обращается по вышеуказанному адресу за комментариями. Но, результат мы получим не в окно браузера, а в переменную. Которую и передадим в блок контента. Как вы уже наверное догадались, нам надо реализовать Контроллер и Вид (обойдемся пока без модели) для комментариев. Это и будет та самая Триада.
Создайте Контроллер comments.php:
<?php defined('SYSPATH') or die('No direct script access.'); class Controller_Comments extends Controller { public function action_index() { $id = $this->request->param('id'); $content = View::factory('/comments/show') ->bind('comments', $comments); // Вместо switch-case будет вызов Модели switch($id) { case 'article1': $comments = array( array('name' => 'Вася', 'comment' => 'Привет, Петя'), array('name' => 'Петя', 'comment' => 'Привет, Вася'), ); break; case 'article2': $comments = array( array('name' => 'Гена', 'comment' => 'Привет, Мир'), ); break; default: $comments = array(); } $this->response->body($content); } } // Comments
Разберем его подробнее. Поскольку блок комментариев абстрактен сам по себе, ему не нужны ни заголовок, ни описание, ни прочие параметры, которые мы прописывали в Базовом Контроллере. Поэтому наследовать мы будем напрямую Controller. В методе мы еще раз получаем название нашей статьи (переменная $id). После этого в переменную $content передаем наш файл Вида для комментариев и массив комментариев $comments. Этот массив в условиях боевого сайта мы будем получать из базы данных, исходя из $id и относящихся к нему комментариев. А пока я реализовал это посредством switch — case.
Наконец, строкой $this->response->body($content) обрабатывается и отдается все, что в итоге получилось, но поскольку вызов Контроллера производился из другого Контроллера, а не напрямую, то отдается в переменную, а не в окно браузера.
Теперь давайте добьем код до конца. Осталось сделать Вид для комментариев.
В папке с шаблонами создайте папку comments и в ней файл show.php. В нем будет просто цикл обработки массива:
<?php foreach($comments as $comment): ?> <strong>Имя пользователя:</strong><br /> <?php echo $comment['name']; ?><br /> <strong>Комментарий пользователя:</strong><br /> <?php echo $comment['comment']; ?> <br /><hr /><br /> <?php endforeach; ?>
Сразу проверьте, что при переходе по адресу http://kohana/comments/article1 у вас выводятся комментарии Васи и Пети, а по адресу http://kohana/comments/article2 комментарий Гены. Если все работает, то остался последний штрих. В шаблоне article.php допишите вывод комментариев. Должно получится как-то так:
Статья <?php echo $article; ?> <br /><br /> <?php echo $comments; ?>
Все. Теперь заходите в статьи и наслаждайтесь тем, что от статей одни только заголовки, а юзеры уже что-то понаписали . Вот мой Образец.
Напоследок хочется еще сказать вот что. Мне лично не очень будет нравиться, если всякие проходимцы будут лазить по адресам вроде http://kohana/comments/article1, т.е. сразу смотреть комментарии, в обход статей. Хотя адресов они могут и не знать, но все же. Закрыть такой несанкционированный доступ очень просто. Допишем в comments.php условие:
if(Request::initial() === Request::current()) Request::initial()->redirect(URL::site());
И таким образом отсечем нарушителя редиректом. Нечего лазить там, где не надо. На этом совсем все. Переваривайте информацию, пробуйте и до встречи в следующем уроке.
<< Назад | Вперед >> |
Пожалуйста, зарегистрируйтесь для комментирования.
Добавлю, что для проверки можно также использовать is_initial(), которое вернет True или False.
как при помощи валидации kohana организовать аякс проверку?
Очень просто:
В случае ошибок есть массив $errors. Его отправляешь ответом — если не прошла валидация, если все ок отправляешь true. А сам механизм очень простой, в данном случае можно обойтись JSON и Jquery.
добавьте в описание, еще то что можно передавать параметры.
ErrorException [ Fatal Error ]: Class ‘Pagination’ not found
У меня в 3.2 нету такого модуля и класса, как я нагуглил — его надо устанавливать дополнительно
верно. это я случайно с этого
http://kohanaframework.su/modules/pagination
урока скопипастил и не посмотрел. щас поправлю.
Поясните пж не много эту строчку:
$comments = Request::factory($comments_url)->execute();
Назначение мне понятно, но не понятна реализация. Т.е здесь происходит обращение к контроллеру ‘comments’, а то что идёт после «/» — в качестве параметра?
execute() — что делает этот метод?
После / идет идентификатор текущей статьи. Нам ведь нужно знать, к какой статье выводить комментарии.
А метод execute запускает запрос, который был составлен. Этот метод в Кохане используется часто, посмотрите те же базы данных.
$request = Request::initial();
if(Request::initial() === Request::current())
Request::initial()->redirect(URL::site());
Извиняюсь, а зачем мы создаем переменную $request.
Если мы ей не пользуемся?
Дада. Лишнее. Сейчас уберу. Вообще лучше проверку производить через
Добрый день.
Какие еще есть способы запроса из контроллера другого контроллера?
Допустим я хочу сделать так, что бы страница собиралась как конструктор из нескольких элементов (например: меню, левый блок, правый блок, центральная часть).
Для каждого такого элемента логично было бы написать свой контроллер и при формировании страницы подключать требуемые контроллеры.
Если подключать требуемые контроллеры как описано в данном уроке, то надо писать для каждого свой «роут». Тогда «роутов» может быть очень много. Есть другие способы обращения из контроллера к другому контроллеру?
Ну можно роут один универсальный написать. Разграничить регулярками.
И вы уверены, что вам нужно на все части создавать контроллеры и нельзя обойтись просто подключением шаблона ?
Можно конечно обойтись и одним контроллером. Но мне кажется, что идея HMVC: разбивать задачу на более мелкие части (в данном случае имеются ввиду — контроллеры элементов страницы) и разрабатывать отдельно каждую часть.
Вот мне и интересно какие еще есть методы обращения к другим контроллерам?
Кстати, в моем случае, через «роуты» и не получиться. Ведь мне надо, чтобы вызывался контроллер /page/, а в нем уже вызывались контроллеры элементов страницы, которые не имеют самостоятельного адреса в URL.
Как такое можно реализовать?
Не обойтись одним контроллером, а обойтись одним роутом Контроллеры конечно должны быть разные.
А элементы страницы можно вызывать через роуты. Посмотрите, как вызов капчи устроен. Между прочим тоже через роут.
Спасибо Вам за ответы. Я подниму эту тему на форуме, что бы не засорять уроки.
Что-то я не совсем улавливаю концепцию.. Если на разных разделах сайта (контролерах) у меня масса одних и тех же блоков, то их разумно реализовать в отдельных контроллерах. Но получается что при сборке страницы я вынужден каждый блок формировать через отдельный запрос к серверу..? Вместо локального обращения к внутренним ресурсам системы? Это же замедляет отдачу контента.. Я на типе кавычек пытаюсь экономить в РНР.. а тут такой тормоз..? Скажите что я ошибаюсь..
В Kohana 3.3 больше не поддерживается метод Request->redirect(‘url’). Можно использовать HTTP::redirect(‘url’).