Página de inicio del blog

Vamos a crear la página de inicio mostrando tus entradas recientes.

Antes de empezar, deberías conocer al menos algunos conceptos básicos sobre el patrón de diseño Modelo-Vista-Presentador (similar a MVC):

  • Modelo – capa de manipulación de datos. Está completamente separada del resto de la aplicación. Sólo se comunica con los presentadores.
  • Vista – capa de definición del front-end. Presenta los datos solicitados al usuario utilizando plantillas.
  • Presentador (o Controlador) – una capa de conexión. El presentador conecta el modelo y la vista. Maneja las solicitudes, pide datos al Modelo y luego los pasa a la Vista actual.

En el caso de una aplicación muy simple como nuestro blog, la capa Modelo consistirá en realidad sólo de consultas a la base de datos en sí – no necesitamos ningún código PHP extra para ello. Sólo necesitamos crear las capas Presentador y Vista. En Nette, cada Presentador tiene sus propias Vistas, así que continuaremos con ambas simultáneamente.

Creando la Base de Datos con Adminer

Para almacenar los datos, utilizaremos la base de datos MySQL porque es la opción más común entre los desarrolladores web. Pero si no te gusta, siéntete libre de usar una base de datos de tu elección.

Preparemos la base de datos que almacenará las entradas de nuestro blog. Podemos empezar de forma muy simple – sólo con una única tabla para las entradas.

Para crear la base de datos podemos descargar Adminer, o puede utilizar otra herramienta para la gestión de bases de datos.

Abramos Adminer y creemos una nueva base de datos llamada quickstart.

Creamos una nueva tabla llamada posts y añadimos estas columnas

  • id int, haga clic en autoincrementar (AI)
  • title varchar, longitud 255
  • content texto
  • created_at timestamp

Debería tener este aspecto:

CREATE TABLE `posts` (
	`id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
	`title` varchar(255) NOT NULL,
	`content` text NOT NULL,
	`created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB CHARSET=utf8;

Es muy importante utilizar la tabla de almacenamiento InnoDB. Verás la razón más adelante. Por ahora, sólo tienes que elegir eso y enviar. Ya puedes pulsar Guardar.

Intenta añadir algunas entradas de blog de ejemplo antes de que implementemos la capacidad de añadir nuevas entradas directamente desde nuestra aplicación.

INSERT INTO `posts` (`id`, `title`, `content`, `created_at`) VALUES
(1,	'Article One',	'Lorem ipusm dolor one',	CURRENT_TIMESTAMP),
(2,	'Article Two',	'Lorem ipsum dolor two',	CURRENT_TIMESTAMP),
(3,	'Article Three',	'Lorem ipsum dolor three',	CURRENT_TIMESTAMP);

Conexión a la base de datos

Ahora, cuando la base de datos está creada y tenemos algunos posts en ella, es el momento de mostrarlos en nuestra nueva y brillante página.

Primero, necesitamos decirle a nuestra aplicación qué base de datos usar. La configuración de la conexión a la base de datos se almacena en config/common.neon. Configura la conexión DSN y tus credenciales. Debería verse así:

database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*

Tenga en cuenta la sangría al editar este archivo. El formato NEON acepta tanto espacios como tabuladores, pero no ambos a la vez. El archivo de configuración del Proyecto Web utiliza tabuladores por defecto.

Inyección de la conexión a la base de datos

El presentador HomePresenter, que listará los artículos, necesita una conexión a la base de datos. Para recibirla, escribe un constructor como este:

<?php
namespace App\Presenters;

use Nette;
use Nette\Application\UI\Form;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	// ...
}

Cargar mensajes de la base de datos

Ahora vamos a obtener las entradas de la base de datos y pasarlas a la plantilla, que luego renderizará el código HTML. Para esto está el método render:

public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}

El presentador tiene ahora un método render renderDefault() que pasa los datos a una vista llamada default. Las plantillas del presentador se pueden encontrar en app/Presenters/templates/{PresenterName}/{viewName}.latte, así que en este caso la plantilla se encontrará en app/Presenters/templates/Home/default.latte. En la plantilla, ahora está disponible una variable llamada $posts, que contiene los mensajes de la base de datos.

Plantilla

Existe una plantilla genérica para toda la página (llamada layout, con cabecera, hojas de estilo, pie de página, …) y luego plantillas específicas para cada vista (por ejemplo, para mostrar la lista de entradas del blog), que pueden anular algunas partes de la plantilla layout.

Por defecto, la plantilla de diseño se encuentra en templates/@layout.latte, que contiene:

...
{include content}
...

{include content} inserta un bloque llamado content en la plantilla principal. Puedes definirlo en las plantillas de cada vista. En este caso, editaremos el archivo Home/default.latte así:

{block content}
	Hello World
{/block}

Define el bloque content, que se insertará en el diseño. Si actualizas el navegador, verás una página con el texto “Hola mundo” (en el código fuente también con la cabecera y el pie HTML definidos en @layout.latte).

Vamos a mostrar las entradas del blog – editaremos la plantilla así:

{block content}
	<h1>My blog</h1>

	{foreach $posts as $post}
	<div class="post">
		<div class="date">{$post->created_at|date:'j. n. Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content|truncate:256}</div>
	</div>
	{/foreach}
{/block}

Si actualizas tu navegador, verás la lista de entradas de tu blog. La lista no es muy elegante o colorido, así que siéntase libre de añadir un poco de CSS brillante a www/css/style.css y vincularlo en un diseño:

	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...

La etiqueta {foreach} itera sobre todas las entradas pasadas a la plantilla en la variable $posts y muestra un fragmento de código HTML para cada entrada. Igual que lo haría un código PHP.

Lo de |date se llama filtro. Los filtros se utilizan para dar formato a la salida. Este filtro en particular convierte una fecha (por ejemplo 2013-04-12) a su forma más legible (12. 4. 2013). El filtro |truncate trunca la cadena hasta la longitud máxima especificada, y añade una elipsis al final si la cadena está truncada. Dado que se trata de una vista previa, no tiene sentido mostrar el contenido completo del artículo. Puede encontrar otros filtros por defecto en la documentación o crear los suyos propios si lo necesita.

Una cosa más. Podemos hacer el código un poco más corto y por lo tanto más simple. Podemos reemplazar Latte tags por n:attributes así:

{block content}
	<h1>My blog</h1>

	<div n:foreach="$posts as $post" class="post">
		<div class="date">{$post->created_at|date:'F j, Y'}</div>

		<h2>{$post->title}</h2>

		<div>{$post->content}</div>
	</div>
{/block}

El n:foreach, simplemente envuelve el div con un bloque foreach (hace exactamente lo mismo que el bloque de código anterior).

Resumen

Tenemos una base de datos MySQL muy simple con algunas entradas de blog en ella. La aplicación se conecta a la base de datos y muestra una lista simple de los mensajes.