Выводим новости
На прошлом занятии мы подключили xPDO и попробовали его в работе. Сегодня мы можем добавим в БД пару новостей и вывести их на отдельных страницах.
Для этого нам нужно будет научить контроллер News определять, что именно запросил пользователь: список новостей или отдельную новость. Это несложно, нужно только проверять, что указано в url после /news/.
Пишем контроллер Brevis\Controllers\News с вот такой инициализацией:
public function initialize(array $params = array()) {
if (empty($params)) {
$this->redirect("/{$this->name}/");
}
elseif (!empty($params[0])) {
$c = $this->core->xpdo->newQuery('Brevis\Model\News');
if (is_numeric($params[0])) {
$c->where(array('id' => $params[0]));
}
else {
$c->where(array('alias' => $params[0]));
}
if ($news = $this->core->xpdo->getObject('Brevis\Model\News', $c)) {
$alias = $news->get('alias');
if (isset($params[1]) || $params[0] != $alias) {
$this->redirect("/{$this->name}/{$alias}");
}
else {
$this->item = $news;
}
}
else {
$this->redirect("/{$this->name}/");
}
}
return true;
}
Давайте разберёмся, что здесь происходит?
Первое правило осталось неизменным - если мы запрашиваем страницу /news без завершающего слеша, то происходит редирект на правильный адрес.
Дальше мы проверяем наличие первого параметра в $params[0]. Он может содержать или число (id новости) или не число (alias новости). Мы ищем нашу новость в зависимости от типа переменной.
Если нашли, но запрошенный параметр не соответствует alias новости - делаем редирект. Также мы делаем редирект на каноничный url, если параметров больше, чем 1. Под этот случай попадает и косая на конце адреса новости.
Если же все проверки пройдены, то мы сохраняем полученную новость в свойство $item контроллера, чтобы работать с ним дальше.
В итоге, верный адрес новости у нас - http://s1889.bez.modhost.pro/news/the-first и никакой другой. При попытке ввести что-то не то, будет редирект или на правильный адрес, или на раздел /news/.
Теперь в методе run нам нужно просто проверять $this->item на пустоту. Если в него что-то загружено, то выводить страницу отдельной новости. Если нет - то список всех новостей.
Вывод новости
Основной метод контроллера новостей я написал такой:
/**
* @return string
*/
public function run() {
if ($this->item) {
$data = array(
'title' => $this->item->get('pagetitle'),
'pagetitle' => $this->item->get('pagetitle'),
'longtitle' => $this->item->get('longtitle'),
'content' => $this->item->get('text'),
);
}
else {
$data = array(
'title' => 'Новости',
'pagetitle' => 'Новости',
'items' => $this->getItems(),
'content' => '',
);
}
return $this->template('news', $data, $this);
}
Проверка наличия загруженной новости, и если её нет - то вывод списка новостей отдельным методом getItems().
В этом методе тоже ничего сложного:
/**
* Выбор последних новостей с обрезкой текста
*
* @return array
*/
public function getItems() {
$rows = array();
$c = $this->core->xpdo->newQuery('Brevis\Model\News');
$c->select($this->core->xpdo->getSelectColumns('Brevis\Model\News', 'News'));
$c->sortby('id', 'DESC');
$c->limit($this->limit);
if ($c->prepare() && $c->stmt->execute()) {
while ($row = $c->stmt->fetch(\PDO::FETCH_ASSOC)) {
$cut = strpos($row['text'], "\n");
if ($cut !== false) {
$row['text'] = substr($row['text'], 0, $cut);
$row['cut'] = true;
}
else {
$row['cut'] = false;
}
$rows[] = $row;
}
}
else {
$this->core->log('Не могу выбрать новости:' . print_r($c->stmt->errorInfo(), true));
}
return $rows;
}
Обычный запрос через xPDO, с лимитом, указанным в News::limit. Из интересного только обрезка текста новости до первого встреченного символа переноса строки и добавление записи cut об этом в массив.
Теперь нужно добавить новый шаблон news.tpl и прописать в нём оформление.
Шаблон новостей
Здесь мы работаем с блоком content:
{block 'content'}
{if $items}
{foreach $items as $item}
<div class="news">
<h3><a href="/news/{$item.alias}">{$item.pagetitle}</a></h3>
<p>{$item.text}</p>
{if $item.cut}
<a href="/news/{$item.alias}" class="btn btn-default">Читать далее →</a>
{/if}
</div>
{/foreach}
{else}
<a href="/news/">← Назад</a>
{parent}
{/if}
{/block}
Если есть переменная $items, то перебираем и оформляем её в цикле. Если нет - то выводим ссылку на все новости и контент страницы, как это указано в базовом шаблоне.
Подключаем Markdown
Не знаю, как вам, а вот лично мне не нравится, что в наших новостях нет переносов строки и весь текст идёт сплошняком.
Можно, конечно, добавить замену \n на br, но лучше сразу подключить обработчик разметки Markdown - отличный класс Parsedown. Тем более, что это займёт не более 5 минут.
Меняем composer.json:
"require": {
"php": ">=5.3.0",
"fenom/fenom": "2.*",
"xpdo/xpdo": "3.0.*@dev",
"erusev/parsedown": "1.5.*"
},
Добавляем в ядро загрузку парсера:
public function getParser() {
if (!$this->parser) {
$this->parser = new Parsedown();
}
return $this->parser;
}
Добавляем обработку текста парсером при выводе новости:
'content' => $this->core->getParser()->text($this->item->get('text')),
Вот и всё - проще некуда. Метод Core::getParser() возвращает нам объкт Parsedown, в котором мы используем text().
Заключение
Мы сделали вывод списка новостей, отдельной новости и добавили в проект работу с разметкой Markdown.
Всё это заняло у нас минут 20 от силы.
На мой взгляд, на этом наш курс обучения можно смело заканчивать, потому что мы:
-
Хорошо познакомились с ООП в PHP
-
Написали собственное ядро сайта с простеньким роутером и контроллерами запросов
-
Отрефакторили наш проект для соответствия PSR-4 и познакомились с Composer
-
Подключили Fenom для шаблонизации
-
Подключили xPDO для работы с БД, написали схему и сгенерировали модель
-
Подключили Parsedown и вывели новости на сайте
Таким образом, мы создали полностью рабочий PHP сайт, который можно бесконечно расширять в любые стороны. Добавлять контроллеры, шаблоны, прописывать вывод информации из БД и всё это с минимальными усилиями.
Если у вас есть вопросы - задавайте. Если нужно рассказать еще что-то - предлагайте, я не против написать еще одно занятие.
0
👍
👎
❤️
🔥
😮
😢
😀
😡
1 774
13.06.2015, 08:33:00
2 комментария
Семён Лобачевский
14.06.2015, 22:17:23
Спасибо за уроки! Все ясно и понятно, осталось больше попрактиковаться, чтобы уложились новые знания. Ещё интересен вопрос по безопасности приложений, на что обращать больше внимания и может есть какие-то приёмы для проверки взломоустойчивости написанного кода.
14.06.2015, 22:55:25
Основное правило простое - всегда ожидать подвоха от юзера и проверять все входящие от него данные. Большинство возможных проблем по работе с БД мы сразу закрываем, используя xPDO. А вообще, тема эта очень обширная, советую начать отсюда.
bezumkin.ru
Личный сайт Василия Наумкина
Прямой эфир
Василий Наумкин
01.07.2024, 11:56:41
Да, верно, именно так.
А в контроллере, скорее всего, ловить данные методом post.
Василий Наумкин
26.06.2024, 09:38:15
О, точно, вылезает если не залогинен.
Спасибо, исправил!
Василий Наумкин
09.04.2024, 04:45:01
> Ошибка 500
Это не похоже на ошибку Nginx, это скорее всего ошибка PHP - надо смотреть его логи.
...
russel gal
09.03.2024, 20:17:18
> А этот стоило написать хотя бы затем, чтобы получить комментарий от юзера, который ничего не писал...
Александр Наумов
27.01.2024, 03:06:18
Василий, спасибо!
Извини, тупанул.