Страница с публикация
Сега ще създадем още една страница на блога, която ще показва една конкретна публикация.
Трябва да създадем нов 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
.
Резюме
Имаме база данни с публикации и уеб приложение, което има два изгледа – първият показва преглед на всички публикации, а вторият показва една конкретна публикация.