место в рейтинге
  • 68662
  • 223
  • 36
Нравится блог?
Подписывайтесь!

Zend Framework: создаем блог. Шаг 2

Продолжаем копипасту разработку блога на Zend Framework. В планах на этот раз у нас создание категорий, отображение постов в них и вывод комментариев к постам. Готовы? Поехали.

Начнем с моделей. Нам нужно вывести список категорий и при выборе определенной категории, вывести посты принадлежащие ей. Давайте добавим в нашу модель постов новый метод для выбора постов по ID'шнику категории. Вот полный код обновленной модели постов.

 

 

 

  1. <?php
  2.  
  3. /**
  4.  * Posts model
  5.  *
  6.  * @author Kanat Gailimov, http://gailimov.info
  7.  * @copyright Copyright (c) Kanat Gailimov (http://gailimov.info) 2011
  8.  */
  9.  
  10. class Application_Model_DbTable_Posts extends Zend_Db_Table_Abstract
  11. {
  12. /**
  13.   * Db table name
  14.   *
  15.   * @var string
  16.   */
  17. protected $_name = 'zf_posts';
  18.  
  19. /**
  20.   * Get post by ID
  21.   *
  22.   * @param int $id ID of post
  23.   * @return array
  24.   */
  25. public function getById($id)
  26. {
  27. $id = intval($id);
  28. $row = $this->fetchRow('id = ' . $id);
  29. if (!$row) {
  30. throw new Exception('Ахтунг! Выборка поста не удалась :(');
  31. }
  32. return $row;
  33. }
  34.  
  35. /**
  36.   * Get by category's ID
  37.   *
  38.   * @param int $categoryId ID of category
  39.   * @return array
  40.   */
  41. public function getByCategoryId($categoryId)
  42. {
  43. $categoryId = intval($categoryId);
  44. // Формируем условие запроса
  45. $select = $this->select()->where('category_id = ' . $categoryId)
  46. ->order('created_at DESC')
  47. ->order('id DESC');
  48. // Выполняем запрос
  49. $row = $this->fetchAll($select);
  50. if (!$row) {
  51. throw new Exception('Ахтунг! Выборка категорий не удалась :(');
  52. }
  53. return $row->toArray();
  54. }
  55. }

 

 

 

Как видите, мы добавили метод getByCategoryId($categoryId). Он принимает в качестве параметра ID'шник категории и возвращает посты соотвествующие ей в виде массива. Обратите внимание на условия запроса: они образуют как бы "паровозик" из методов. Также нам нужно получать данные по самой категории. А именно название (а если бы были мета-теги, то и их). Для этого нам нужно создать еще одну модель для категорий. Приведу ее код:

 

 

 

  1. <?php
  2.  
  3. /**
  4.  * Categories model
  5.  *
  6.  * @author Kanat Gailimov, http://gailimov.info
  7.  * @copyright Copyright (c) Kanat Gailimov (http://gailimov.info) 2011
  8.  */
  9.  
  10. class Application_Model_DbTable_Categories extends Zend_Db_Table_Abstract
  11. {
  12. /**
  13.   * DB table name
  14.   *
  15.   * @var string
  16.   */
  17. protected $_name = 'zf_categories';
  18.  
  19. /**
  20.   * Get by ID
  21.   *
  22.   * @param int $id ID
  23.   * @return array
  24.   */
  25. public function getById($id)
  26. {
  27. $id = intval($id);
  28. $row = $this->fetchRow('id = ' . $id);
  29. if (!$row) {
  30. throw new Exception('Ахтунг! Выборка данных по категории не прошла :(');
  31. }
  32. return $row;
  33. }
  34. }

 

 

 

Здесь у нас метод, принимающий в качестве параметра ID'шник и возращающий данные по категории соответствующей ему. Теперь нам нужно создать модель для комментариев. В нем будет метод, выбирающий комментарии по ID'шнику поста. Давайте напишем его:

 

 

 

  1. <?php
  2.  
  3. /**
  4.  * Comments model
  5.  *
  6.  * @author Kanat Gailimov, http://gailimov.info
  7.  * @copyright Copyright (c) Kanat Gailimov (http://gailimov.info) 2011
  8.  */
  9.  
  10. class Application_Model_DbTable_Comments extends Zend_Db_Table_Abstract
  11. {
  12. /**
  13.   * DB table name
  14.   *
  15.   * @var string
  16.   */
  17. protected $_name = 'zf_comments';
  18.  
  19. /**
  20.   * Get comments by post's ID
  21.   *
  22.   * @param int $postId ID of post
  23.   * @return array
  24.   */
  25. public function getByPostId($postId)
  26. {
  27. $postId = intval($postId);
  28. $row = $this->fetchAll('post_id = ' . $postId);
  29. if (!$row) {
  30. throw new Exception('Ахтунг! Попытка получить комменты не удалась :(');
  31. }
  32. return $row->toArray();
  33. }
  34. }

 

 

 

Давайте теперь изменим наш контроллер. Я сразу приведу готовый код и ниже поясню:

 

 

 

  1. <?php
  2.  
  3. class IndexController extends Zend_Controller_Action
  4. {
  5.  
  6. public function init()
  7. {
  8. // Уставливаем название блога
  9. $this->view->title = 'Тестовый блог на Zend Framework';
  10. // Устанавливаем разделитель для тега title с помощью хелперов
  11. // headTitle() и setSeparator()
  12. $this->view->headTitle()->setSeparator(' | ');
  13. // Передаем заголовок в тег title, с помошью хелпера headTitle()
  14. $this->view->headTitle($this->view->title);
  15.  
  16. // Создаем экземпляр модели категорий
  17. $categories = new Application_Model_DbTable_Categories();
  18. // Выбираем все категории
  19. $this->view->categories = $categories->fetchAll();
  20. }
  21.  
  22. public function indexAction()
  23. {
  24. // Создаем экземпляр модели постов
  25. $posts = new Application_Model_DbTable_Posts();
  26. // Выбираем все посты
  27. // Формируем условие
  28. $select = $posts->select()->order('created_at DESC')
  29. ->order('id DESC');
  30. // Выполняем запрос
  31. $this->view->posts = $posts->fetchAll($select);
  32. }
  33.  
  34. /**
  35.   * View post
  36.   *
  37.   * @return void
  38.   */
  39. public function postAction()
  40. {
  41. // Берем ID'шник из параметра
  42. $id = intval($this->_getParam('id', 0));
  43. if ($id > 0) {
  44. // Создаем экземпляр модели постов и выбираем посты по ID
  45. $post = new Application_Model_DbTable_Posts();
  46. $this->view->post = $post->getById($id);
  47. // Устанавливаем заголовок для поста в тег title
  48. $this->view->postTitle = $this->view->post['title'];
  49. $this->view->headTitle($this->view->postTitle);
  50. // Получаем комменты к посту
  51. $comments = new Application_Model_DbTable_Comments();
  52. $this->view->comments = $comments->getByPostId($id);
  53. }
  54. }
  55.  
  56. /**
  57.   * View category
  58.   *
  59.   * @return void
  60.   */
  61. public function categoryAction()
  62. {
  63. $id = intval($this->_getParam('id', 0));
  64. if ($id > 0) {
  65. $posts = new Application_Model_DbTable_Posts();
  66. $this->view->posts = $posts->getByCategoryId($id);
  67. // Получаем данные по категории
  68. $category = new Application_Model_DbTable_Categories();
  69. $this->view->category = $category->getById($id);
  70. // Устанавливаем заголовок для категории в тег title
  71. $this->view->categoryTitle = $this->view->category['title'];
  72. $this->view->headTitle($this->view->categoryTitle);
  73. }
  74. }
  75.  
  76. }

 

 

 

Первое изменение произошло в методе init(). В него мы добавили вывод всех категорий для отображения в сайдбаре. Изменение номер два - в методе postAction() добавлен вывод комментариев к посту. И наконец последнее измение - добавление нового метода categoryAction(). Он будет срабатывать при выборе определенной категории. Его можно добавить как ручками, так и с помощью Zend_Tool - командой "zf create action category index". При втором варианте также создастся соответствующий вид (application/views/scripts/category.phtml), иначе его надо будет добавить самому. Итак в методе categoryAction() мы получаем из параметров ID. Далее если ID больше нуля, то получаем посты, данные по категории и устанавливаем заголовок для категории.

И наконец осталось набросать вьюшку. Для начала подредактируем layout (application/layouts/scripts/layout.phtml). В месте где у нас в сайдбаре выводился список категорий, добавим реальный список из БД:

 

 

 

  1. <aside>
  2. <section>
  3. <header>
  4. <h4>Категории</h4>
  5. </header>
  6. <ul>
  7. <?php foreach ($this->categories as $category) : ?>
  8. <li><a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'category', 'id' => $category->id)) ?>"><?php echo $category->title ?></a></li>
  9. <?php endforeach ?>
  10. </ul>
  11. </section>
  12. </aside>

 

 

 

Я не стал снова приводить код всего макета, а показал сам сайдбар. Здесь просто цикл foreach, в котором выводятся категории. Все должно быть знакомо и понятно. А вот и сама вьюшка категорий (application/views/scripts/index/category.phtml):

 

 

 

  1. <section id="content">
  2. <section id="posts">
  3. <?php if (count($this->posts) < 1) : ?>
  4. <article>
  5. <p>Посты закончились</p>
  6. </article>
  7. <?php else : foreach ($this->posts as $post) : ?>
  8. <article>
  9. <header>
  10. <h2><a href="<?php echo $this->url(array('controller' => 'index', 'action' => 'post', 'id' => $post['id'])) ?>"><?php echo $this->escape($post['title']) ?></a></h2>
  11. </header>
  12. <?php echo $post['blog_post'] ?>
  13. <p><?php echo $this->escape($post['created_at']) ?></p>
  14. </article>
  15. <?php endforeach; endif ?>
  16. </section> <!-- posts -->
  17. </section> <!-- content -->

 

 

 

Тут все как на главной. Ну а теперь добавим вывод комментариев в наш вид для отдельного поста (application/views/scripts/index/post.phtml):

 

 

 

  1. <section id="content">
  2. <section id="posts">
  3. <article>
  4. <header>
  5. <h2><?php echo $this->post['title'] ?></h2>
  6. </header>
  7. <?php echo $this->post['blog_post'] ?>
  8. <p class="date"><?php echo $this->post['created_at'] ?></p>
  9. </article>
  10. </section> <!-- posts -->
  11. <section id="comments">
  12. <header>
  13. <h3>Комменты:</h3>
  14. </header>
  15. <?php if (empty($this->comments)) : ?>
  16. <article>
  17. <p>Комментов нет</p>
  18. </article>
  19. <?php else : foreach ($this->comments as $comment) : ?>
  20. <article>
  21. <?php if (!empty($comment['url'])) : ?>
  22. <header>
  23. <h5><a href="<?php echo $comment['url'] ?>"><?php echo $this->escape($comment['name']) ?></a></h5>
  24. </header>
  25. <?php else : ?>
  26. <header>
  27. <h5><?php echo $this->escape($comment['name']) ?></h5>
  28. </header>
  29. <?php endif ?>
  30. <p><?php echo $comment['blog_comment'] ?></p>
  31. <p class="date"><?php echo $comment['created_at'] ?></p>
  32. </article>
  33. <?php endforeach; endif ?>
  34. </section> <!-- comments -->
  35. </section> <!-- content -->

 

 

 

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

Канат Гайлимов KanatGailimov
Мальчик-красавчик
16 февраля 2011, 16:07
1423

Загрузка...
Loading...

Комментарии

Levak2
0
0
Мне этого не понять((
Levak2
0
0
Наверное полезно)
megido
0
0
потом ещё cache добавь)
до кэша пока не дошел (в мане) :)
Пеши исчо :)
плюсанул в карму
пара ошибок:
application/views/scripts/category.phtml нужно заменить на application/views/scripts/index/category.phtml
application/views/scripts/index.post.phtml в место точки слэш нужен application/views/scripts/index/post.phtml
спасибо) ты мой самый внимательный читатель :)
Прост я делаю все что описано:)
Пробовал осваивать zf, но дальше установки не пошло. Сейчас с приходом твоих записей вторая попытка:)
приятно слышать, что твои посты кому-то полезны :)
я тут поразмышлял по поводу urlов. сейчас они такого вида: testblog/index/category/id/2 , testblog/index/post/id/3 индекс явно лишний... быть может стоит перебрать, чтобы получалось testblog/post/id/3, testblog/category/id/2 ?
до URL'ов и роутинга еще дойдем :) Хочется полное ЧПУ, т.е. вместо ID, осмысленные названия
а еще у меня не работал baseUrl(). заменил на serverUrl()
странно, а код из моего архива не проверял?
у тебя там baseUrl()
в браузере смотрю исходный код - ничего не выводит
Ну попробуй убрать baseUrl() и посмотри.
baseUrl() выводит путь к твоему приложению, т.е. /zftest/public/ У меня все именно так

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

Спасибо за открытие блога в Yvision.kz! Чтобы убедиться в отсутствии спама, все комментарии новых пользователей проходят премодерацию. Соблюдение правил нашей блог-платформы ускорит ваш переход в категорию надежных пользователей, не нуждающихся в премодерации. Обязательно прочтите наши правила по указанной ссылке: Правила

Также можно нажать Ctrl+Enter

Популярные посты

Казком берет комиссии за оплаты по карте. Почему на это закрывают глаза Visa и MasterCard?!

Казком берет комиссии за оплаты по карте. Почему на это закрывают глаза Visa и MasterCard?!

Покупаешь в супермаркете продукты на 5000 тенге и банк забирает себе еще 30-50 тенге. То есть, продукты обошлись уже не в 5000, а в 5050 тенге.
ValentinaVladimirska
25 мая 2017 / 22:56
  • 13461
  • 26
Узаконенное варварство в стране, принимающей «EPXO». Еще далеко нам до «топ-30 развитых стран»

Узаконенное варварство в стране, принимающей «EPXO». Еще далеко нам до «топ-30 развитых стран»

В продвинутых государствах едва ли поймут, почему в столь развитом, успешном и преуспевающем Казахстане от имени и по заданию властей творятся такие зверства над животными.
openqazaqstan
24 мая 2017 / 12:12
  • 10827
  • 102
Вырубка деревьев в Алматы под БРТ. Проект уже нанес городу экологический ущерб

Вырубка деревьев в Алматы под БРТ. Проект уже нанес городу экологический ущерб

Как ранее уже сообщалось из-за строительства БРТ в Алматы пострадают значительное количество деревьев. На прошлой неделе вырублены первые вязы и клён, - под расширение проезжей части на улице...
SKYFALL
24 мая 2017 / 17:20
  • 10532
  • 14
Поддержим пенсией жиреющие банки! На что казахстанцам разрешат досрочно тратить свои накопления в ЕНПФ

Поддержим пенсией жиреющие банки! На что казахстанцам разрешат досрочно тратить свои накопления в ЕНПФ

Со стороны ЕНПФ в очередной раз прозвучало крайне неоднозначное заявление, от которого, на наш взгляд, лучше было бы воздержаться.
openqazaqstan
23 мая 2017 / 11:08
  • 9935
  • 32
Системная коррупция стала главной угрозой для Казахстана. У нас воруют миллиардами

Системная коррупция стала главной угрозой для Казахстана. У нас воруют миллиардами

Коррупционные отношения вышли на такой уровень, что они уже начинают дискредитировать всю систему управления.
openqazaqstan
26 мая 2017 / 13:45
  • 8435
  • 34
Что бы ни сделал пешеход – все равно водитель сядет

Что бы ни сделал пешеход – все равно водитель сядет

Вопрос о равной ответственности водителя и пешехода при наезде на последних, только-только начинают обдумывать в высоких кабинетах. Но, пока государственные головы думают, водители продолжают...
Mirogloff
22 мая 2017 / 23:29
  • 5149
  • 32
Да-да, я знаю, пора выходить замуж. Есть ли у меня еще время и, пожалуйста, уточните сколько?

Да-да, я знаю, пора выходить замуж. Есть ли у меня еще время и, пожалуйста, уточните сколько?

Итак давайте сразу начистоту. Мне 29. Не замужем, никогда не была, детей нет. В душе я совсем не чувствую этот возраст. Каждый раз когда задумываюсь об этом больше чем на 3 минуты, меня накрывает...
user2017
23 мая 2017 / 10:57
Пока полицейские будут прощать, им будут бить и по чести, и по лицу

Пока полицейские будут прощать, им будут бить и по чести, и по лицу

Судья Алмалинского районного суда Куаныш Арипов ломает стереотипы отношения граждан к представителям Фемиды. Напавшему на полицейского экс-сотруднику алматинского акимата он назначил наказание выше...
Mirogloff
24 мая 2017 / 16:41
  • 4003
  • 9
Аблязов загробным голосом декларирует «ДВК-2». Монолог обиженного человека

Аблязов загробным голосом декларирует «ДВК-2». Монолог обиженного человека

Последний монолог Аблязова о «продолжении борьбы с режимом» и «ДВК-2», при всём желании, не выглядел как какой-то политический манифест.
openqazaqstan
25 мая 2017 / 13:53
  • 3285
  • 62