Página única de postagem

Vamos adicionar outra página ao nosso blog, que exibirá o conteúdo de um determinado post do blog.

Precisamos criar um novo método de renderização, que irá buscar um post específico no blog e passá-lo para o modelo. Ter esta visão em HomePresenter não é legal porque se trata de um post de blog, não da página inicial. Então, vamos criar uma nova classe PostPresenter e colocá-la em app/UI/Post/. Ela precisará de uma conexão de banco de dados, então coloque o código injeção de banco de dados lá novamente.

O PostPresenter deve se parecer com isto:

<?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);
	}
}

Temos que definir um namespaces correto App\UI\Post para nosso apresentador. Isso depende do mapeamento do apresentador.

O método renderShow requer um argumento – a identificação do posto a ser exibido. Em seguida, ele carrega o posto do banco de dados e passa o resultado para o modelo.

No modelo Home/default.latte, adicionamos 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. Esta tag também encaminha a identificação do correio como argumento.

O mesmo podemos escrever em breve usando n:attribute:

...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...

O atributo n:href é similar à tag {link}.

O modelo para a ação Post:show ainda não existe. Podemos abrir um link para este post. Tracy mostrará um erro, porque Post/show.latte ainda não existe. Se você vir qualquer outro relatório de erro, provavelmente terá que ligar o mod_rewrite em seu servidor web.

Por isso, criaremos Post/show.latte com este conteúdo:

{block content}

<p><a n:href="Home:default">← back to posts list</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>

Vamos dar uma olhada nas partes individuais.

A primeira linha inicia a definição de um bloco nomeado chamado “conteúdo”, que vimos anteriormente. Ele será exibido em um modelo de layout. Como você pode ver, a etiqueta final {/block} está faltando. Ela é opcional.

A segunda linha fornece um backlink para a lista de postagens do blog, para que o usuário possa navegar suavemente para frente e para trás em nosso blog. Usamos novamente o atributo n:href, portanto a Nette se encarregará de gerar a URL para nós. O link aponta para a ação default do apresentador Home (você também poderia escrever n:href="Home:", pois a ação default pode ser omitida).

A terceira linha formata o carimbo de tempo de publicação com um filtro, como já sabemos.

A quarta linha exibe o título do post do blog como um <h1> título. Há uma parte que você pode não estar familiarizado, e que é n:block="title". Você pode adivinhar o que ela faz? Se você leu cuidadosamente as partes anteriores, mencionamos n: attributes. Este é outro exemplo. É equivalente a:

{block title}<h1>{$post->title}</h1>{/block}

Em palavras simples, ele redefine um bloco chamado title. O bloco é definido no modelo layout (/app/UI/@layout.latte:11) e, como no OOP, ele é anulado aqui. Portanto, a página é <title> conterá o título do post exibido. Anulamos o título da página e tudo o que precisávamos era n:block="title". Ótimo, não é?

A quinta e última linha do modelo exibe o conteúdo completo do seu post.

Verificação da identificação do posto

O que acontece se alguém altera a URL e insere id que não existe? Devemos fornecer ao usuário um bom erro de “página não encontrada”. Vamos atualizar o método de renderização em PostPresenter:

public function renderShow(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);
	if (!$post) {
		$this->error('Post not found');
	}

	$this->template->post = $post;
}

Se o correio não puder ser encontrado, ligando para $this->error(...), aparecerá uma página 404 com uma mensagem agradável e compreensível. Note que em seu ambiente de desenvolvimento (em seu laptop), você não verá a página de erro. Em vez disso, Tracy mostrará a exceção com todos os detalhes, o que é bastante conveniente para o desenvolvimento. Você pode verificar os dois modos, basta alterar o valor passado para setDebugMode em Bootstrap.php.

Sumário

Temos um banco de dados com posts em blogs e um aplicativo web com duas visualizações – o primeiro exibe o resumo de todos os posts recentes e o segundo exibe um post específico.