Продолжаем копипасту разработку блога на Zend Framework. В планах на этот раз у нас создание категорий, отображение постов в них и вывод комментариев к постам. Готовы? Поехали.
Начнем с моделей. Нам нужно вывести список категорий и при выборе определенной категории, вывести посты принадлежащие ей. Давайте добавим в нашу модель постов новый метод для выбора постов по ID'шнику категории. Вот полный код обновленной модели постов.
<?php /** * Posts model * * @author Kanat Gailimov, http://gailimov.info * @copyright Copyright (c) Kanat Gailimov (http://gailimov.info) 2011 */ class Application_Model_DbTable_Posts extends Zend_Db_Table_Abstract { /** * Db table name * * @var string */ protected $_name = 'zf_posts'; /** * Get post by ID * * @param int $id ID of post * @return array */ public function getById($id) { $row = $this->fetchRow('id = ' . $id); if (!$row) { throw new Exception('Ахтунг! Выборка поста не удалась :('); } return $row; } /** * Get by category's ID * * @param int $categoryId ID of category * @return array */ public function getByCategoryId($categoryId) { // Формируем условие запроса $select = $this->select()->where('category_id = ' . $categoryId) ->order('created_at DESC') ->order('id DESC'); // Выполняем запрос $row = $this->fetchAll($select); if (!$row) { throw new Exception('Ахтунг! Выборка категорий не удалась :('); } return $row->toArray(); } }
Как видите, мы добавили метод getByCategoryId($categoryId). Он принимает в качестве параметра ID'шник категории и возвращает посты соотвествующие ей в виде массива. Обратите внимание на условия запроса: они образуют как бы "паровозик" из методов. Также нам нужно получать данные по самой категории. А именно название (а если бы были мета-теги, то и их). Для этого нам нужно создать еще одну модель для категорий. Приведу ее код:
<?php /** * Categories model * * @author Kanat Gailimov, http://gailimov.info * @copyright Copyright (c) Kanat Gailimov (http://gailimov.info) 2011 */ class Application_Model_DbTable_Categories extends Zend_Db_Table_Abstract { /** * DB table name * * @var string */ protected $_name = 'zf_categories'; /** * Get by ID * * @param int $id ID * @return array */ public function getById($id) { $row = $this->fetchRow('id = ' . $id); if (!$row) { throw new Exception('Ахтунг! Выборка данных по категории не прошла :('); } return $row; } }
Здесь у нас метод, принимающий в качестве параметра ID'шник и возращающий данные по категории соответствующей ему. Теперь нам нужно создать модель для комментариев. В нем будет метод, выбирающий комментарии по ID'шнику поста. Давайте напишем его:
<?php /** * Comments model * * @author Kanat Gailimov, http://gailimov.info * @copyright Copyright (c) Kanat Gailimov (http://gailimov.info) 2011 */ class Application_Model_DbTable_Comments extends Zend_Db_Table_Abstract { /** * DB table name * * @var string */ protected $_name = 'zf_comments'; /** * Get comments by post's ID * * @param int $postId ID of post * @return array */ public function getByPostId($postId) { $row = $this->fetchAll('post_id = ' . $postId); if (!$row) { throw new Exception('Ахтунг! Попытка получить комменты не удалась :('); } return $row->toArray(); } }
Давайте теперь изменим наш контроллер. Я сразу приведу готовый код и ниже поясню:
<?php class IndexController extends Zend_Controller_Action { public function init() { // Уставливаем название блога $this->view->title = 'Тестовый блог на Zend Framework'; // Устанавливаем разделитель для тега title с помощью хелперов // headTitle() и setSeparator() $this->view->headTitle()->setSeparator(' | '); // Передаем заголовок в тег title, с помошью хелпера headTitle() $this->view->headTitle($this->view->title); // Создаем экземпляр модели категорий $categories = new Application_Model_DbTable_Categories(); // Выбираем все категории $this->view->categories = $categories->fetchAll(); } public function indexAction() { // Создаем экземпляр модели постов $posts = new Application_Model_DbTable_Posts(); // Выбираем все посты // Формируем условие $select = $posts->select()->order('created_at DESC') ->order('id DESC'); // Выполняем запрос $this->view->posts = $posts->fetchAll($select); } /** * View post * * @return void */ public function postAction() { // Берем ID'шник из параметра if ($id > 0) { // Создаем экземпляр модели постов и выбираем посты по ID $post = new Application_Model_DbTable_Posts(); $this->view->post = $post->getById($id); // Устанавливаем заголовок для поста в тег title $this->view->postTitle = $this->view->post['title']; $this->view->headTitle($this->view->postTitle); // Получаем комменты к посту $comments = new Application_Model_DbTable_Comments(); $this->view->comments = $comments->getByPostId($id); } } /** * View category * * @return void */ public function categoryAction() { if ($id > 0) { $posts = new Application_Model_DbTable_Posts(); $this->view->posts = $posts->getByCategoryId($id); // Получаем данные по категории $category = new Application_Model_DbTable_Categories(); $this->view->category = $category->getById($id); // Устанавливаем заголовок для категории в тег title $this->view->categoryTitle = $this->view->category['title']; $this->view->headTitle($this->view->categoryTitle); } } }
Первое изменение произошло в методе init(). В него мы добавили вывод всех категорий для отображения в сайдбаре. Изменение номер два - в методе postAction() добавлен вывод комментариев к посту. И наконец последнее измение - добавление нового метода categoryAction(). Он будет срабатывать при выборе определенной категории. Его можно добавить как ручками, так и с помощью Zend_Tool - командой "zf create action category index". При втором варианте также создастся соответствующий вид (application/views/scripts/category.phtml), иначе его надо будет добавить самому. Итак в методе categoryAction() мы получаем из параметров ID. Далее если ID больше нуля, то получаем посты, данные по категории и устанавливаем заголовок для категории.
И наконец осталось набросать вьюшку. Для начала подредактируем layout (application/layouts/scripts/layout.phtml). В месте где у нас в сайдбаре выводился список категорий, добавим реальный список из БД:
<aside> <section> <header> <h4>Категории</h4> </header> <ul> <?php foreach ($this->categories as $category) : ?> <li><a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'category', 'id' => $category->id)) ?>"><?php echo $category->title ?></a></li> <?php endforeach ?> </ul> </section> </aside>
Я не стал снова приводить код всего макета, а показал сам сайдбар. Здесь просто цикл foreach, в котором выводятся категории. Все должно быть знакомо и понятно. А вот и сама вьюшка категорий (application/views/scripts/index/category.phtml):
<section id="content"> <section id="posts"> <article> <p>Посты закончились</p> </article> <?php else : foreach ($this->posts as $post) : ?> <article> <header> <h2><a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'post', 'id' => $post['id'])) ?>"><?php echo $this->escape($post['title']) ?></a></h2> </header> <?php echo $post['blog_post'] ?> <p><?php echo $this->escape($post['created_at']) ?></p> </article> <?php endforeach; endif ?> </section> <!-- posts --> </section> <!-- content -->
Тут все как на главной. Ну а теперь добавим вывод комментариев в наш вид для отдельного поста (application/views/scripts/index/post.phtml):
<section id="content"> <section id="posts"> <article> <header> <h2><?php echo $this->post['title'] ?></h2> </header> <?php echo $this->post['blog_post'] ?> <p class="date"><?php echo $this->post['created_at'] ?></p> </article> </section> <!-- posts --> <section id="comments"> <header> <h3>Комменты:</h3> </header> <article> <p>Комментов нет</p> </article> <?php else : foreach ($this->comments as $comment) : ?> <article> <header> <h5><a href="<?php echo $comment['url'] ?>"><?php echo $this->escape($comment['name']) ?></a></h5> </header> <?php else : ?> <header> <h5><?php echo $this->escape($comment['name']) ?></h5> </header> <?php endif ?> <p><?php echo $comment['blog_comment'] ?></p> <p class="date"><?php echo $comment['created_at'] ?></p> </article> <?php endforeach; endif ?> </section> <!-- comments --> </section> <!-- content -->
Теперь можете запустить браузер, набрать URL вашего проекта и лицезреть результат. Поклацайте по ссылкам, все должно работать. В следующий раз займемся добавлением комментариев. Так что если вы до сих пор не подписались на RSS, самое время исправиться. На этом у меня все, до следующего поста. Исходники лежат тут.