Crear y editar artículos

¡Estupendo! Tenemos un blog nuevo y genial, la gente debate activamente en los comentarios y por fin tenemos algo de tiempo para programar más. Aunque Adminer es una gran herramienta, no resulta muy cómodo para escribir artículos nuevos. Quizá sea el momento adecuado de crear un formulario sencillo para añadir artículos nuevos directamente desde la aplicación. Hagámoslo.

Empecemos diseñando la interfaz de usuario:

  1. En la portada añadimos un enlace “Write new post”.
  2. Ese enlace mostrará un formulario con un campo de título y un textarea para el contenido del artículo.
  3. Al pulsar el botón Guardar, el artículo se guardará en la base de datos.

Más adelante añadiremos también la autenticación y permitiremos añadir artículos nuevos solo a los usuarios conectados. Pero eso lo dejamos para después. ¿Qué código tenemos que escribir ahora para que todo funcione?

  1. Crear un presenter nuevo con un formulario para añadir artículos.
  2. Definir un callback que se dispare tras el envío correcto del formulario y guarde el artículo nuevo en la base de datos.
  3. Crear una plantilla nueva para el formulario.
  4. Añadir un enlace al formulario en la plantilla de la página principal.

Presenter nuevo

Llamemos al nuevo presenter EditPresenter y guardémoslo en app/Presentation/Edit/EditPresenter.php. También necesita conectarse a la base de datos, así que aquí escribimos de nuevo un constructor que exige 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 artículos

Los formularios y los componentes ya los vimos al añadir el soporte de comentarios. Si todavía no lo tiene claro, repase cómo funcionan los formularios y los componentes, aquí le esperamos ;)

Ahora añada este método al EditPresenter:

protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Title:')
		->setRequired();
	$form->addTextArea('content', 'Content:')
		->setRequired();

	$form->addSubmit('send', 'Save and publish');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

Guardar el artículo nuevo desde el formulario

Sigamos añadiendo el método manejador:

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

	$this->flashMessage('Post was published successfully.', 'success');
	$this->redirect('Post:show', $post->id);
}

Una explicación rápida: obtiene los valores del formulario, los inserta en la base de datos, crea un mensaje para el usuario indicando que el artículo se guardó correctamente y redirige a la página en la que ese artículo está publicado, para que pueda ver qué aspecto tiene.

Página para crear un artículo nuevo

Creemos ahora la plantilla Edit/create.latte:

{block content}
<h1>New post</h1>

{control postForm}

A estas alturas todo debería estar claro. La última línea renderiza el formulario que acabamos de crear.

También podríamos crear el método renderCreate() correspondiente, pero no hace falta. No necesitamos obtener ningún dato de la base de datos ni pasárselo a la plantilla, así que el método estaría vacío. En esos casos, el método no tiene por qué existir.

Enlace para crear artículos

Probablemente ya sepa cómo añadir un enlace a EditPresenter y a su acción create. Pruébelo.

Basta con añadir lo siguiente al archivo app/Presentation/Home/default.latte:

<a n:href="Edit:create">Write new post</a>

Editar artículos

Añadamos ahora la posibilidad de editar los artículos existentes. Será muy sencillo. Ya tenemos el formulario postForm y podemos usarlo también para editar.

Añadiremos al EditPresenter una nueva página edit:

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

	if (!$post) {
		$this->error('Post not found');
	}

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

Y creamos la plantilla correspondiente Edit/edit.latte:

{block content}
<h1>Edit post</h1>

{control postForm}

Y actualizamos el método postFormSucceeded, que podrá tanto añadir un artículo nuevo (como hace ahora) como editar los existentes:

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('Post was published successfully.', 'success');
	$this->redirect('Post:show', $post->id);
}

Cuando se indica el parámetro id, significa que se está editando un artículo. En ese caso comprobamos que el artículo existe realmente y, si es así, lo actualizamos en la base de datos. Si no se indica el id, significa que hay que añadir un artículo nuevo.

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

Ahora puede añadir un enlace a la plantilla app/Presentation/Post/show.latte:

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

Resumen

El blog funciona, la gente comenta a toda velocidad y ya no dependemos de Adminer para añadir artículos nuevos. Es completamente independiente y hasta la gente normal puede publicar en él. Pero un momento: probablemente no esté bien que cualquiera, y quiero decir cualquiera de internet, pueda publicar en nuestro blog. Hace falta alguna forma de autenticación para que solo los usuarios conectados puedan publicar. Eso lo añadiremos en el siguiente capítulo.