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.