Strona z wkładem
Teraz stwórzmy kolejną stronę bloga, która będzie wyświetlała jeden konkretny post.
Musimy stworzyć nową metodę renderującą, która pobiera jeden konkretny artykuł i przekazuje go do szablonu. Posiadanie
tej metody w HomePresenter
nie jest zbyt miłe, ponieważ mówimy o artykule, a nie o stronie głównej. Stwórzmy
więc PostPresenter
w app/UI/Post/
. Ten prezenter również musi połączyć się z bazą danych, więc
tutaj znowu napiszemy konstruktor, który będzie wymagał połączenia z bazą danych.
PostPresenter
Mogłoby to wtedy wyglądać tak:
<?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);
}
}
Nie zapomnij uwzględnić prawidłowej przestrzeni nazw App\UI\Post
, która podlega ustawieniom mapowania prezentera.
Metoda renderShow
wymaga jednego argumentu – ID jednego konkretnego artykułu, który ma być wyświetlony.
Następnie pobiera ten artykuł z bazy danych i przekazuje go do szablonu.
W szablonie Home/default.latte
wstawiamy link do akcji Post:show
.
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
Znacznik {link}
generuje adres URL, który wskazuje na akcję Post:show
. Przekazuje również
identyfikator postu jako argument.
To samo można napisać w skrócie, używając atrybutu n::
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
Atrybut n:href
jest podobny do znacznika {link}
.
Nie ma jednak jeszcze szablonu dla akcji Post:show
. Możemy spróbować otworzyć link do tego postu. Tracy wyświetla błąd, ponieważ szablon Post/show.latte
jeszcze nie
istnieje. Jeśli widzisz inny komunikat o błędzie, prawdopodobnie musisz włączyć mod_rewrite
na serwerze
internetowym.
Stwórzmy więc szablon Post/show.latte
z tą treścią:
{block content}
<p><a n:href="Home:default">← zpět na výpis příspěvků</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>
Teraz przejdźmy przez poszczególne części szablonu.
Pierwsza linia zaczyna się od zdefiniowania bloku o nazwie “content” tak jak to było na stronie głównej. Ten blok
będzie ponownie wyświetlany w głównym szablonie. Jak widać, brakuje znacznika końcowego {/block}
. Jest
to opcja.
W kolejnym wierszu znajduje się link zwrotny do listy artykułów na blogu, dzięki czemu użytkownik może łatwo poruszać
się między listą artykułów a jednym konkretnym. Ponieważ używamy atrybutu n:href
, Nette samo zajmuje się
generowaniem linków. Link wskazuje na działanie prezentera default
Home
(możemy też napisać
n:href="Home:"
, bo działanie o nazwie default
można pominąć, zostanie wypełnione
automatycznie).
Trzecia linia formatuje datę zrzutu za pomocą znanego nam już filtra.
Czwarta linia wyświetla tytuł wpisu na blogu w znaczniku HTML <h1>
. Ten znacznik zawiera atrybut,
którego być może nie znasz (n:block="title"
). Czy zgadniesz, co to robi? Jeśli uważnie przeczytałeś poprzedni
rozdział, wiesz już, że jest to n:atribut
. To jest ich kolejny przykład, który jest równoważny:
{block title}<h1>{$post->title}</h1>{/block}
Po prostu ten blok predefiniuje blok o nazwie title
. Blok ten jest już zdefiniowany w głównym szablonie
layout (/app/UI/@layout.latte:11
) i podobnie jak w przypadku nakładek na metody w OOP, nakłada ten blok w
szablonie głównym w dokładnie taki sam sposób. Więc <title>
strona zawiera teraz nagłówek wyświetlanego
postu, a wszystko co musieliśmy zrobić to użyć jednego prostego atrybutu n:block="title"
. Świetnie, prawda?
Piąta i ostatnia linia szablonu wyświetla całą zawartość jednego konkretnego postu.
Sprawdź identyfikator postu
Co się stanie jeśli ktoś zmieni ID w URL i umieści jakiś nieistniejący id
? Powinniśmy zaoferować
użytkownikowi ładny błąd “page not found”. Zmodyfikujmy więc nieco metodę render w PostPresenter
:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Stránka nebyla nalezena');
}
$this->template->post = $post;
}
Jeśli nie można znaleźć postu, wywołanie $this->error(...)
wyświetli stronę błędu 404 z jasnym
komunikatem. Zauważ, że w trybie deweloperskim (localhost) nie zobaczysz tej strony błędu. Zamiast tego pokaże Tracy ze
szczegółami wyjątku, co jest dość wygodne dla rozwoju. Jeśli chcemy mieć wyświetlane oba tryby, wystarczy zmienić
argument metody setDebugMode
w pliku Bootstrap.php
.
Streszczenie.
Mamy bazę danych z postami i aplikację internetową, która ma dwa widoki – pierwszy pokazuje przegląd wszystkich postów, a drugi pokazuje jeden konkretny post.