Página individual
Vamos a añadir otra página a nuestro blog, que mostrará el contenido de una entrada del blog en particular.
Necesitamos crear un nuevo método de renderizado, que obtendrá una entrada de blog específica y la pasará a la plantilla.
Tener esta vista en HomePresenter
no es agradable porque se trata de una entrada de blog, no de la página principal.
Por lo tanto, vamos a crear una nueva clase PostPresenter
y colocarla en app/UI/Post/
. Necesitará una
conexión a la base de datos, por lo que pondremos el código de inyección a la base de datos allí de nuevo.
El PostPresenter
debería verse así:
<?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);
}
}
Tenemos que establecer un namespaces correcto App\UI\Post
para nuestro presentador. Depende de la asignación del presentador.
El método renderShow
requiere un argumento – el ID de la entrada a mostrar. Luego, carga la entrada desde la
base de datos y pasa el resultado a la plantilla.
En la plantilla Home/default.latte
añadimos un enlace a la acción Post:show
:
...
<h2><a href="{link Post:show $post->id}">{$post->title}</a></h2>
...
La etiqueta {link}
genera una dirección URL que apunta a la acción Post:show
. Esta etiqueta
también reenvía el ID del post como argumento.
Lo mismo podemos escribir en breve utilizando n:attribute:
...
<h2><a n:href="Post:show $post->id">{$post->title}</a></h2>
...
El atributo n:href
es similar a la etiqueta {link}
.
La plantilla para la acción Post:show
aún no existe. Podemos abrir un enlace a este post. Tracy mostrará un error, por qué Post/show.latte
no existe. Si usted ve
cualquier otro informe de error que probablemente tiene que activar mod_rewrite en su servidor web.
Así que vamos a crear Post/show.latte
con este contenido:
{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>
Echemos un vistazo a las partes individuales.
La primera línea inicia la definición de un bloque con nombre llamado “contenido” que vimos antes. Se mostrará
en una plantilla de diseño. Como puedes ver, falta la etiqueta final {/block}
. Es opcional.
La segunda línea proporciona un backlink a la lista de entradas del blog, para que el usuario pueda navegar sin problemas
hacia adelante y hacia atrás en nuestro blog. Volvemos a utilizar el atributo n:href
, por lo que Nette se encargará
de generar la URL por nosotros. El enlace apunta a la acción default
del presentador Home
(también se
podría escribir n:href="Home:"
, ya que la acción default
se puede omitir).
La tercera línea formatea la marca de tiempo de publicación con un filtro, como ya sabemos.
La cuarta línea muestra el título de la entrada del blog como un <h1>
encabezamiento. Hay una parte
con la que quizá no estés familiarizado, y es n:block="title"
. ¿Puedes adivinar lo que hace? Si has leído con
atención las partes anteriores, hemos mencionado n: attributes
. Este es otro ejemplo. Equivale a:
{block title}<h1>{$post->title}</h1>{/block}
En palabras simples, redefine un bloque llamado title
. El bloque está definido en la plantilla de
diseño (/app/UI/@layout.latte:11
) y, al igual que ocurre con la sobreescritura de programación orientada a
objetos, se sobreescribe aquí. Por lo tanto, la página <title>
contendrá el título de la entrada mostrada.
Hemos sobreescrito el título de la página y todo lo que necesitábamos era n:block="title"
. Genial, ¿eh?
La quinta y última línea de la plantilla muestra el contenido completo de tu post.
Comprobando el ID del post
¿Qué pasa si alguien altera la URL e inserta id
que no existe? Deberíamos proporcionar al usuario un bonito
error de “página no encontrada”. Actualicemos el método render en 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;
}
Si la entrada no puede ser encontrada, llamando a $this->error(...)
se mostrará una página 404 con un
mensaje agradable y comprensible. Ten en cuenta que en tu entorno de desarrollo (en tu portátil), no verás la página de error.
En su lugar, Tracy mostrará la excepción con todos los detalles, lo cual es bastante conveniente para el desarrollo. Puede
comprobar ambos modos, simplemente cambie el valor pasado a setDebugMode
en Bootstrap.php
.
Resumen
Tenemos una base de datos con entradas de blog y una aplicación web con dos vistas – la primera muestra el resumen de todas las entradas recientes y la segunda muestra una entrada específica.