Creazione e modifica dei post

Che momento fantastico. Abbiamo un nuovo blog superfigo, la gente discute nei commenti e finalmente abbiamo un po' di tempo per programmare. Anche se ci piace Adminer, non è così comodo scriverci i post del blog. Forse è il momento giusto per aggiungere un semplice modulo per aggiungere nuovi post direttamente dalla nostra applicazione. Facciamolo.

Iniziamo a progettare l'interfaccia utente:

  1. Nella homepage, aggiungiamo un link “Scrivi un nuovo post”.
  2. Verrà visualizzato un modulo con titolo e textarea per il contenuto.
  3. Quando si fa clic sul pulsante Salva, il post viene salvato.

In seguito aggiungeremo anche l'autenticazione e permetteremo solo agli utenti loggati di aggiungere nuovi post. Ma questo lo faremo più avanti. Quale codice dovremo scrivere per farlo funzionare?

  1. Creare un nuovo presenter con un modulo per l'aggiunta di post.
  2. Definire un callback che verrà attivato dopo l'invio del modulo e che salverà il nuovo post nel database.
  3. Creare un nuovo modello per il modulo.
  4. Aggiungere un link al modulo nel modello della pagina principale.

Nuovo presentatore

Nominiamo il nuovo presentatore EditPresenter e salviamolo in app/Presenters/EditPresenter.php. Deve anche connettersi al database, quindi anche in questo caso scriviamo un costruttore che richieda una connessione al database:

<?php
namespace App\Presenters;

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

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

Modulo per il salvataggio dei messaggi

I moduli e i componenti sono già stati trattati quando abbiamo aggiunto il supporto per i commenti. Se siete confusi sull'argomento, andate a vedere di nuovo come funzionano i moduli e i componenti, noi aspetteremo qui ;)

Ora aggiungete questo metodo a 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;
}

Salvare un nuovo messaggio dal modulo

Continuare aggiungendo un metodo di gestione.

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

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

Una breve spiegazione: recupera i valori dal modulo, li inserisce nel database, crea un messaggio per l'utente che indica che il post è stato salvato con successo e reindirizza alla pagina in cui il post è pubblicato, in modo che l'utente possa vederne l'aspetto.

Pagina per la creazione di un nuovo post

Creiamo il modello Edit/create.latte:

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

{control postForm}

A questo punto dovrebbe essere tutto chiaro. L'ultima riga mostra il modulo che stiamo per creare.

Potremmo anche creare un metodo corrispondente renderCreate, ma non è necessario. Non abbiamo bisogno di ottenere alcun dato dal database e di passarlo al template, quindi il metodo sarebbe vuoto. In questi casi, il metodo potrebbe non esistere affatto.

Probabilmente sapete già come aggiungere un link a EditPresenter e alla relativa azione create. Provate.

Basta aggiungere al file app/Presenters/templates/Home/default.latte:

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

Modifica dei messaggi

Aggiungiamo anche la possibilità di modificare i post esistenti. Sarà piuttosto semplice: abbiamo già postForm e possiamo usarlo anche per la modifica.

Aggiungeremo una nuova pagina edit al sito EditPresenter:

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

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

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

E creeremo il modello Edit/edit.latte:

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

{control postForm}

E aggiornare il metodo postFormSucceeded, che potrà sia aggiungere un nuovo post (come fa ora), sia modificare quelli esistenti:

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

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

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

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

Quando viene fornito il parametro postId, significa che si sta modificando un post. In questo caso, controlleremo che il post esista davvero e, in caso affermativo, lo aggiorneremo nel database. Se il parametro postId non viene fornito, significa che verrà aggiunto un nuovo post.

Ma da dove viene postId? È il parametro passato al metodo renderEdit.

Ora è possibile aggiungere un link al modello app/Presenters/templates/Post/show.latte:

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

Sommario

Il blog funziona, le persone commentano rapidamente e non ci affidiamo più all'Adminer per aggiungere nuovi post. È completamente indipendente e anche le persone normali possono scriverci. Ma aspettate, probabilmente non va bene che chiunque, intendo davvero chiunque su Internet, possa postare sul nostro blog. È necessaria una forma di autenticazione, in modo che solo gli utenti loggati possano postare. La aggiungeremo nel prossimo capitolo.