Сторінка окремого запису
Давайте додамо в наш блог ще одну сторінку, на якій відображатиметься вміст одного конкретного запису блогу.
Нам потрібно створити новий метод render, який буде отримувати один
конкретний запис блогу і передавати його в шаблон. Мати це подання в
HomePresenter
не дуже приємно, тому що йдеться про запис у блозі, а не
про головну сторінку. Отже, давайте створимо новий клас PostPresenter
і помістимо його в app/UI/Post/
. Йому знадобиться з'єднання з базою
даних, тому знову помістіть туди код впровадження залежності.
PostPresenter
має виглядати наступним чином:
<?php
namespace App\UI\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\UI\Post
для
нашого презентера. Це залежить від mapping 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:attribute:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Атрибут n:href
аналогічний тегу {link}
.
Шаблон для дії Post:show
ще не існує. Ми можемо відкрити посилання
на цей пост. Tracy покаже помилку про те, що
app/UI/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:'j.m.Y'}</div>
<h1 n:block="title">{$post->title}</h1>
<div class="post">{$post->content}</div>
Розглянемо деякі моменти.
Перший рядок починає визначення іменованого блоку під назвою
content
, які ми бачили раніше. Він буде відображатися в шаблоні
макета.
Другий рядок містить зворотне посилання на список постів блогу, щоб
користувач міг плавно переміщатися по нашому блогу вперед і назад. Ми
знову використовуємо атрибут n:href
, тому Nette подбає про генерацію
URL для нас. Посилання вказує на дію default
презентера Home
(можна просто написати n:href="Home:"
, оскільки дія default
може
бути опущена).
Третій рядок форматує тимчасову мітку публікації за допомогою
фільтра date
, як ми вже знаємо.
Четвертий рядок відображає заголовок запису блогу у вигляді
заголовка <h1>
. Є частина, з якою ви, можливо, не знайомі, це
n:block="title"
. Чи можете ви здогадатися, що вона робить? Якщо ви
уважно читали попередні частини, ми згадували n: атрибуты
. Ось ще
один приклад. Це еквівалентно:
{block title}<h1>{$post->title}</h1>{/block}
Простіше кажучи, він перевизначає блок під назвою title
. Блок
визначено в шаблоні макета (/app/UI/@layout.latte:11
) і, як і у випадку
з перевизначенням ООП, він перевизначається тут. Тому <title>
сторінки буде містити заголовок відображуваного поста. Ми
перевизначили заголовок сторінки, і все, що нам було потрібно, це
n:block="title"
. Чудово, чи не так?
П'ятий і останній рядок шаблону відображає повний зміст вашого поста.
Перевірка ідентифікатора поста
Що станеться, якщо хтось змінить URL і вставить неіснуючий id
? Ми
повинні надати користувачеві красиву сторінку помилки “сторінку не
знайдено”. Давайте оновимо метод render
у файлі
PostPresenter.php
:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Страница не найдена!');
}
$this->template->post = $post;
}
Якщо пост не може бути знайдений, виклик $this->error(...)
покаже
сторінку 404 з красивим і зрозумілим повідомленням. Зверніть увагу, що в
режимі розробки ви не побачите сторінку помилки. Натомість Tracy покаже
виняток із повною інформацією, що досить зручно для розробки. Ви можете
перевірити обидва режими, просто змінивши значення, що передається в
setDebugMode
на Bootstrap.php
.
Підіб'ємо підсумок
У нас є база даних із записами блогу і веб-додаток із двома поданнями: перше відображає зведення всіх останніх записів, а друге – один конкретний запис.