Página com a postagem
Agora criaremos outra página do blog, que exibirá uma postagem específica.
Precisamos criar um novo método de renderização que obterá um artigo específico e o passará para o template. Ter este
método no HomePresenter não é muito elegante, pois estamos falando de um artigo e não da página inicial.
Portanto, criaremos um PostPresenter em app/Presentation/Post/. Este presenter também precisa se
conectar ao banco de dados, então escreveremos novamente um construtor que exigirá a conexão com o banco de dados.
O PostPresenter poderia, portanto, ter a seguinte aparência:
<?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);
}
}
Não devemos esquecer de indicar o namespace correto App\Presentation\Post, que está sujeito à configuração
de mapeamento de presenters.
O método renderShow requer um argumento – o ID de um artigo específico que deve ser exibido. Em seguida,
ele carrega este artigo do banco de dados e o passa para o template.
No template Home/default.latte, inseriremos um link para a ação Post:show.
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
A tag {link} gera um endereço URL que aponta para a ação Post:show. Também passa o ID da
postagem como argumento.
Podemos escrever o mesmo de forma abreviada usando um n:atributo:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
O atributo n:href é análogo à tag {link}.
No entanto, ainda não existe um template para a ação Post:show. Podemos tentar abrir o link para esta
postagem. O Tracy exibirá um erro porque o template Post/show.latte
ainda não existe. Se você vir outra mensagem de erro, provavelmente precisará habilitar o mod_rewrite no
servidor web.
Criaremos, portanto, o template Post/show.latte com este conteúdo:
{block content}
<p><a n:href="Home:default">← voltar para a lista de postagens</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>
Agora vamos percorrer as partes individuais do template.
A primeira linha começa a definição do bloco chamado “content”, assim como na página inicial. Este bloco será
novamente exibido no template principal. Como você pode ver, falta a tag final {/block}. Ela é, na verdade,
opcional.
Na linha seguinte, há um link de volta para a lista de artigos do blog, para que o usuário possa navegar facilmente entre a
lista de artigos e um artigo específico. Como estamos usando o atributo n:href, o Nette cuidará da geração dos
links. O link aponta para a ação default do presenter Home (podemos escrever também
n:href="Home:", pois a ação chamada default pode ser omitida, ela é completada automaticamente).
A terceira linha formata a exibição da data usando o filtro que já conhecemos.
A quarta linha exibe o título do blog na tag HTML <h1>. Esta tag contém um atributo que talvez
você não conheça (n:block="title"). Consegue adivinhar o que ele faz? Se você leu a parte anterior com
atenção, já sabe que se trata de um n:atributo. Este é outro exemplo deles, que é equivalente a:
{block title}<h1>{$post->title}</h1>{/block}
Simplificando, este bloco redefine o bloco chamado title. Este bloco já está definido no template principal
layout (/app/Presentation/@layout.latte:11) e, assim como na sobreposição de métodos em OOP, este bloco no
template principal é sobreposto da mesma forma. Portanto, o <title> da página agora contém o título da
postagem exibida, e bastou usar apenas um simples atributo n:block="title". Ótimo, não é?
A quinta e última linha do template exibe todo o conteúdo de uma postagem específica.
Verificação do ID da postagem
O que acontece se alguém alterar o ID na URL e inserir algum id inexistente? Devemos oferecer ao usuário um
erro agradável do tipo “página não encontrada”. Modificaremos, portanto, um pouco o método de renderização no
PostPresenter:
public function renderShow(int $id): void
{
$post = $this->database
->table('posts')
->get($id);
if (!$post) {
$this->error('Página não encontrada');
}
$this->template->post = $post;
}
Se a postagem não puder ser encontrada, chamando $this->error(...) exibiremos uma página de erro 404 com uma
mensagem compreensível. Atenção: no modo de desenvolvimento (localhost), você não verá esta página de erro. Em vez disso,
o Tracy aparecerá com detalhes sobre a exceção, o que é bastante vantajoso para o desenvolvimento. Se quisermos exibir
ambos os modos, basta alterar o argumento do método setDebugMode no arquivo Bootstrap.php.
Resumo
Temos um banco de dados com postagens e uma aplicação web que tem duas views – a primeira exibe uma visão geral de todas as postagens e a segunda exibe uma postagem específica.