Сторінка з постом
Тепер ми створимо ще одну сторінку блогу, яка буде відображати один конкретний пост.
Нам потрібно створити новий render-метод, який отримає одну конкретну
статтю і передасть її в шаблон. Мати цей метод у HomePresenter
не дуже
гарно, оскільки ми говоримо про статтю, а не про головну сторінку.
Створимо PostPresenter
у app/Presentation/Post/
. Цей presenter також потребує
підключення до бази даних, тому тут ми знову напишемо конструктор, який
вимагатиме підключення до бази даних.
PostPresenter
може виглядати так:
<?php
namespace App\Presentation\Post;
use Nette;
use Nette\Application\UI\Form;
final class PostPresenter extends Nette\Application\UI\Presenter
{
public function __construct(
private Nette\Database\Explorer $database,
) {
}
public function renderShow(int $id): void
{
$this->template->post = $this->database
->table('posts')
->get($id);
}
}
Не забудемо вказати правильний простір імен App\Presentation\Post
, який
підпорядковується налаштуванню мапування presenter'ів.
Метод renderShow
вимагає один аргумент – ID однієї конкретної
статті, яка має бути відображена. Потім він завантажує цю статтю з бази
даних і передає її в шаблон.
У шаблон Home/default.latte
вставимо посилання на дію Post:show
.
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
Тег {link}
генерує URL-адресу, яка вказує на дію Post:show
. Він
також передає ID поста як аргумент.
Те саме можна записати скорочено за допомогою n:атрибута:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Атрибут n:href
є аналогом тегу {link}
.
Однак для дії Post:show
ще не існує шаблону. Можемо спробувати
відкрити посилання на цей пост. Tracy відобразить
помилку, оскільки шаблон Post/show.latte
ще не існує. Якщо ви бачите
інше повідомлення про помилку, то, ймовірно, вам доведеться увімкнути
mod_rewrite
на веб-сервері.
Створимо шаблон Post/show.latte
з таким вмістом:
{block content}
<p><a n:href="Home:default">← назад до списку постів</a></p>
<div class="date">{$post->created_at|date:'F j, Y'}</div>
<h1 n:block="title">{$post->title}</h1>
<div class="post">{$post->content}</div>
Тепер розглянемо окремі частини шаблону.
Перший рядок починає визначення блоку з назвою “content”, так само як це
було на головній сторінці. Цей блок знову буде відображений у
головному шаблоні. Як бачите, відсутній кінцевий тег {/block}
. Він є
необов'язковим.
На наступному рядку є посилання назад на список статей блогу, щоб
користувач міг легко переміщатися між списком статей та однією
конкретною. Оскільки ми використовуємо атрибут n:href
, Nette саме
подбає про генерацію посилань. Посилання вказує на дію default
presenter'а Home
(можна також написати n:href="Home:"
, оскільки дія з
назвою default
може бути пропущена, вона доповниться
автоматично).
Третій рядок форматує виведення дати за допомогою фільтра, який ми вже знаємо.
Четвертий рядок відображає заголовок блогу в HTML-тегу
<h1>
. Цей тег містить атрибут, який ви, можливо, не знаєте
(n:block="title"
). Вгадаєте, що він робить? Якщо ви уважно читали
попередню частину, то вже знаєте, що це n:атрибут
. Це ще один їх
приклад, який є еквівалентним до:
{block title}<h1>{$post->title}</h1>{/block}
Простіше кажучи, цей блок перевизначає блок з назвою title
. Цей
блок вже визначений у головному layout шаблоні
(/app/Presentation/@layout.latte:11
), і так само, як при перевизначенні методів в
ООП, точно так само цей блок у головному шаблоні буде перевизначений.
Отже, <title>
сторінки тепер містить заголовок відображеного
поста, і для цього нам знадобилося використати лише один простий
атрибут n:block="title"
. Чудово, чи не так?
П'ятий і останній рядок шаблону відображає весь вміст одного конкретного поста.
Перевірка ID поста
Що станеться, якщо хтось змінить ID в URL і вставить якесь неіснуюче
id
? Ми повинні запропонувати користувачеві гарну помилку типу
“сторінка не знайдена”. Трохи змінимо render-метод у PostPresenter
:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Сторінку не знайдено');
}
$this->template->post = $post;
}
Якщо пост не може бути знайдений, викликом $this->error(...)
ми
відобразимо сторінку помилки 404 зі зрозумілим повідомленням. Зверніть
увагу, що в режимі розробки (localhost) ви цю сторінку помилки не побачите.
Замість неї з'явиться Tracy з деталями про виняток, що досить зручно для
розробки. Якщо ми хочемо побачити обидва режими, достатньо лише
змінити аргумент методу setDebugMode
у файлі Bootstrap.php
.
Підсумок
У нас є база даних з постами та веб-застосунок, який має два представлення – перше відображає огляд усіх постів, а друге – один конкретний пост.