Creación y edición de entradas

¡Esto es genial! Tenemos un blog nuevo súper genial, la gente discute intensamente en los comentarios y finalmente tenemos un poco de tiempo para seguir programando. Aunque Adminer es una gran herramienta, no es del todo ideal para escribir nuevas entradas de blog. Aparentemente, es el momento adecuado para crear un formulario simple para agregar nuevas entradas directamente desde la aplicación. Vamos a ello.

Comencemos diseñando la interfaz de usuario:

  1. En la página de inicio, agregaremos un enlace “Escribir nueva entrada”.
  2. Este enlace mostrará un formulario con un título y un área de texto para el contenido de la entrada.
  3. Cuando hagamos clic en el botón Guardar, la entrada se guardará en la base de datos.

Más tarde, también agregaremos inicio de sesión y permitiremos agregar entradas solo a los usuarios que hayan iniciado sesión. Pero eso será más tarde. ¿Qué código necesitamos escribir ahora para que todo funcione?

  1. Crearemos un nuevo presenter con un formulario para agregar entradas.
  2. Definiremos un callback que se ejecutará después de enviar el formulario con éxito y que guardará la nueva entrada en la base de datos.
  3. Crearemos una nueva plantilla en la que estará dicho formulario.
  4. Agregaremos un enlace al formulario en la plantilla de la página principal.

Nuevo presenter

Llamaremos al nuevo presenter EditPresenter y lo guardaremos en app/Presentation/Edit/. También necesita conectarse a la base de datos, por lo que aquí nuevamente escribiremos un constructor que requerirá una conexión a la base de datos:

<?php
namespace App\Presentation\Edit;

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

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

Formulario para guardar entradas

Ya hemos explicado los formularios y componentes al crear comentarios. Si todavía no está claro, ve a repasar la creación de formularios y componentes, nosotros esperaremos aquí mientras tanto ;)

Ahora agreguemos este método al presenter EditPresenter:

protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Título:')
		->setRequired();
	$form->addTextArea('content', 'Contenido:')
		->setRequired();

	$form->addSubmit('send', 'Guardar y publicar');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

Guardar nueva entrada desde el formulario

Continuamos agregando un método que procesará los datos del formulario:

private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage("La entrada se publicó con éxito.", 'success');
	$this->redirect('Post:show', $post->id);
}

Solo un rápido resumen: este método obtiene los datos del formulario, los inserta en la base de datos, crea un mensaje para el usuario sobre el guardado exitoso de la entrada y redirige a la página con la nueva entrada, para que veamos de inmediato cómo se ve.

Página para crear una nueva entrada

Ahora creemos la plantilla Edit/create.latte:

{block content}
<h1>Nueva entrada</h1>

{control postForm}

Todo debería estar claro ya. La última línea renderiza el formulario que acabamos de crear.

Podríamos crear también el método renderCreate correspondiente, pero no es necesario. No necesitamos obtener ningún dato de la base de datos y pasarlo a la plantilla, por lo que ese método estaría vacío. En tales casos, el método no necesita existir en absoluto.

Enlace para crear entradas

Probablemente ya sepas cómo agregar un enlace a EditPresenter y su acción create. Inténtalo.

Simplemente agrega esto al archivo app/Presentation/Home/default.latte:

<a n:href="Edit:create">Escribir nueva entrada</a>

Edición de entradas

Ahora también agregaremos la opción de editar una entrada. Será muy simple. Ya tenemos listo el formulario postForm y podemos usarlo también para editar.

Agregaremos una nueva página edit al presenter EditPresenter:

public function renderEdit(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);

	if (!$post) {
		$this->error('Entrada no encontrada');
	}

	$this->getComponent('postForm')
		->setDefaults($post->toArray());
}

Y crearemos otra plantilla Edit/edit.latte:

{block content}
<h1>Editar entrada</h1>

{control postForm}

Y modificaremos el método postFormSucceeded, que podrá tanto agregar un nuevo artículo (como lo hace ahora) como editar un artículo ya existente:

private function postFormSucceeded(array $data): void
{
	$id = $this->getParameter('id');

	if ($id) {
		$post = $this->database
			->table('posts')
			->get($id);
		$post->update($data);

	} else {
		$post = $this->database
			->table('posts')
			->insert($data);
	}

	$this->flashMessage('La entrada se publicó con éxito.', 'success');
	$this->redirect('Post:show', $post->id);
}

Si el parámetro id está disponible, significa que vamos a editar la entrada. En ese caso, verificamos que la entrada solicitada realmente exista y, si es así, la actualizamos en la base de datos. Si el parámetro id no está disponible, significa que se debe agregar una nueva entrada.

Pero, ¿de dónde viene el parámetro id? Es el parámetro que se pasó al método renderEdit.

Ahora podemos agregar un enlace a la plantilla app/Presentation/Post/show.latte:

<a n:href="Edit:edit $post->id">Editar entrada</a>

Resumen

El blog ahora es funcional, los visitantes comentan activamente y ya no necesitamos Adminer para publicar. La aplicación es completamente independiente y cualquiera puede agregar una nueva entrada. Espera un momento, probablemente no esté del todo bien que cualquiera – y me refiero a realmente cualquiera con acceso a Internet – pueda agregar nuevas entradas. Se necesita alguna seguridad para que solo un usuario que haya iniciado sesión pueda agregar una nueva entrada. Veremos eso en el próximo capítulo.