Как вы помните (еще об этом написано на главной странице), фреймворк 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());
И таким образом отсечем нарушителя редиректом. Нечего лазить там, где не надо. На этом совсем все. Переваривайте информацию, пробуйте и до встречи в следующем уроке.
<< Назад | Вперед >> |
Пожалуйста, зарегистрируйтесь для комментирования.
скажите пожалуйста куда имеенно вставлять етот код
if(Request::initial() === Request::current())
Request::initial()->redirect(URL::site());
і как он должен виглядить в версии 3.3
спасибо
В Контроллер Comments.php, перед строчкой:
$id = $this->request->param(‘id’);
Лучше после строчки, чтобы $id уже была объявлена.
Тогда редирект можно на саму статью сделать, а не на главную
в 3.3 должно выглядить так:
if(Request::initial() === Request::current())
HTTP::redirect(URL::site());
Вот это и есть то, ради чего стоит использовать Kohana. Все остальные плюшки, не настолько привлекательны, что бы слазить с насиженного CI. Да детка! Вменяемая модульность купе с контроллером шаблонов. Layout, как он есть… а не жалкая эмуляция на костылях созданных своими руками и попутным изобретением велосипеда, как в CI. Спасибо.
я знал, что будет подвох… ну почему я розовый шестигранник? =(
А зачем нам надо давать комментариям отдельный роут и закрывать его доступ?
Я так понимаю вся красота роута в том, что потом мы можем ajax забрать необходимую информацию по роуту комментариев?
Почему в этом случае не сделать модуль который взвращал бы комментарии, без роута. Что-то типа
Comments::get(1); ?
При обращении к статье выдается ошибка ErrorException [ 8 ]: Array to string conversion ~ SYSPATH\classes\Kohana\Log\Writer.php [ 81 ]
Ошибка исправлена, был не верный путь к виду с перебором комментарий
В Кохане 3.3 из класса Request удалили метод redirect().
Поэтому вместо:
Request::initial()->redirect(URL::site());
надо писать так:
Controller::redirect(URL::site());
Или так же можно сделать
HTTP::redirect(URL::site());
Зачем на главную?
$id = $this->request->param(‘id’);
if(Request::initial() === Request::current())
HTTP::redirect(URL::site().’articles/’.$id);
У меня работает такая конструкция:
Странно что тут об этом ни кто ничего не написал, но лично я долго понять не мог почему не выводятся комменты когда заходишь в статья1, статьи2..
Вообщем если
$comments_url = ‘comments/’ . $id;
То получается мы вызываем site.ru/comments/1
а надо site.ru/comments/article1
т.е. правильно будет
$comments_url = ‘comments/article’ . $id;
Ну или в switch изменить сами знаете что. Вариант со switch лучше) Админ, поправляй.