Страница с публикация
Сега ще създадем още една страница на блога, която ще показва една конкретна публикация.
Трябва да създадем нов render метод, който ще получи една конкретна
статия и ще я предаде на шаблона. Да имаме този метод в HomePresenter не
е много хубаво, защото говорим за статия, а не за начална страница.
Затова ще създадем PostPresenter в app/Presentation/Post/. Този презентер
също трябва да се свърже с базата данни, така че тук отново ще напишем
конструктор, който ще изисква връзка с базата данни.
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, което подлежи на настройката на картографиране на
презентери.
Методът 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 на презентера Home (можем да напишем също
n:href="Home:", защото действието с име default може да бъде
пропуснато, допълва се автоматично).
Третият ред форматира извеждането на датата с помощта на филтъра, който вече познаваме.
Четвъртият ред показва заглавието на блога в HTML тага
<h1>. Този таг съдържа атрибут, който може би не познавате
(n:block="title"). Можете ли да познаете какво прави? Ако сте чели
предишната част внимателно, вече знаете, че това е n:атрибут.
Това е още един техен пример, който е еквивалентен на:
{block title}<h1>{$post->title}</h1>{/block}
Просто казано, този блок предефинира блока с име title. Този блок
вече е дефиниран в главния лейаут шаблон
(/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.
Резюме
Имаме база данни с публикации и уеб приложение, което има два изгледа – първият показва преглед на всички публикации, а вторият показва една конкретна публикация.