Nette Documentation Preview

syntax
Creare e modificare gli articoli
********************************

Fantastico! Abbiamo un nuovo blog super figo, la gente discute animatamente nei commenti e finalmente abbiamo un po' di tempo per programmare ancora. Anche se Adminer è un ottimo strumento, non è molto comodo per scrivere nuovi articoli del blog. Forse è il momento giusto per creare un semplice form che permetta di aggiungere nuovi articoli direttamente dall'applicazione. Facciamolo.

Cominciamo progettando l'interfaccia utente:

1. Nella pagina principale aggiungiamo un link "Scrivi un nuovo articolo".
2. Questo link mostrerà un form con un campo per il titolo e una textarea per il contenuto dell'articolo.
3. Quando clicchiamo il pulsante Salva, l'articolo verrà salvato nel database.

Più avanti aggiungeremo anche l'autenticazione e permetteremo di aggiungere nuovi articoli solo agli utenti connessi. Ma facciamolo dopo. Che codice dobbiamo scrivere ora perché tutto funzioni?

1. Creare un nuovo presenter con il form per aggiungere gli articoli.
2. Definire un callback che si attiverà dopo l'invio riuscito del form e salverà il nuovo articolo nel database.
3. Creare un nuovo template per il form.
4. Aggiungere il link al form nel template della pagina principale.


Nuovo presenter
===============

Chiamiamo il nuovo presenter `EditPresenter` e salviamolo in `app/Presentation/Edit/EditPresenter.php`. Anche lui deve connettersi al database, quindi anche qui scriviamo un costruttore che richiede la connessione al database:

```php .{file:app/Presentation/Edit/EditPresenter.php}
<?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,
	) {
	}
}
```


Form per salvare gli articoli
=============================

I form e i componenti li abbiamo già visti quando abbiamo aggiunto il supporto per i commenti. Se non è ancora chiaro, andate a rivedere [come funzionano i form e i componenti |comments#Form per commentare], noi vi aspettiamo qui ;)

Aggiungete ora questo metodo all'`EditPresenter`:

```php .{file:app/Presentation/Edit/EditPresenter.php}
protected function createComponentPostForm(): Form
{
	$form = new Form;
	$form->addText('title', 'Titolo:')
		->setRequired();
	$form->addTextArea('content', 'Contenuto:')
		->setRequired();

	$form->addSubmit('send', 'Salva e pubblica');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}
```


Salvare il nuovo articolo dal form
==================================

Proseguiamo aggiungendo il metodo gestore:

```php .{file:app/Presentation/Edit/EditPresenter.php}
private function postFormSucceeded(array $data): void
{
	$post = $this->database
		->table('posts')
		->insert($data);

	$this->flashMessage('Articolo pubblicato con successo.', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Solo una breve spiegazione: prende i valori dal form, li inserisce nel database, crea per l'utente un messaggio che dice che l'articolo è stato salvato con successo e reindirizza alla pagina in cui l'articolo è pubblicato, così potete vedere come appare.


Pagina per creare un nuovo articolo
===================================

Creiamo ora il template `Edit/create.latte`:

```latte .{file:app/Presentation/Edit/create.latte}
{block content}
<h1>Nuovo articolo</h1>

{control postForm}
```

Ormai dovrebbe essere tutto chiaro. L'ultima riga renderizza il form che abbiamo appena creato.

Potremmo creare anche il metodo `renderCreate()` corrispondente, ma non è necessario. Non dobbiamo prendere alcun dato dal database né passarlo al template, quindi il metodo sarebbe vuoto. In casi del genere il metodo non deve esistere affatto.


Link per creare gli articoli
============================

Probabilmente sapete già come aggiungere un link all'`EditPresenter` e alla sua azione `create`. Provate.

Basta aggiungere al file `app/Presentation/Home/default.latte`:

```latte
<a n:href="Edit:create">Scrivi un nuovo articolo</a>
```


Modificare gli articoli
=======================

Aggiungiamo ora la possibilità di modificare gli articoli esistenti. Sarà molto semplice. Abbiamo già il form `postForm` e lo possiamo usare anche per la modifica.

Aggiungiamo all'`EditPresenter` una nuova pagina `edit`:

```php .{file:app/Presentation/Edit/EditPresenter.php}
public function renderEdit(int $id): void
{
	$post = $this->database
		->table('posts')
		->get($id);

	if (!$post) {
		$this->error('Articolo non trovato');
	}

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

E creiamo il template corrispondente `Edit/edit.latte`:

```latte .{file:app/Presentation/Edit/edit.latte}
{block content}
<h1>Modifica articolo</h1>

{control postForm}
```

E aggiorniamo il metodo `postFormSucceeded`, che saprà sia aggiungere un nuovo articolo (come fa ora), sia modificare quelli esistenti:

```php .{file:app/Presentation/Edit/EditPresenter.php}
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('Articolo pubblicato con successo.', 'success');
	$this->redirect('Post:show', $post->id);
}
```

Quando viene indicato il parametro `id`, significa che si sta modificando un articolo. In tal caso verifichiamo che l'articolo esista davvero e, in caso affermativo, lo aggiorniamo nel database. Se l'`id` non è indicato, significa che va aggiunto un nuovo articolo.

Ma da dove viene l'`id`? È il parametro passato al metodo `renderEdit`.

Ora potete aggiungere un link al template `app/Presentation/Post/show.latte`:

```latte
<a n:href="Edit:edit $post->id">Modifica questo articolo</a>
```


Riepilogo
=========

Il blog funziona, la gente commenta a ritmo serrato e per aggiungere nuovi articoli non dipendiamo più da Adminer. È del tutto indipendente e ci possono scrivere anche le persone comuni. Ma un momento, probabilmente non va bene che chiunque, e intendo davvero chiunque su internet, possa scrivere sul nostro blog. Serve una qualche forma di autenticazione, così che solo gli utenti connessi possano scrivere. La aggiungeremo nel prossimo capitolo.

{{priority: -1}}

Creare e modificare gli articoli

Fantastico! Abbiamo un nuovo blog super figo, la gente discute animatamente nei commenti e finalmente abbiamo un po' di tempo per programmare ancora. Anche se Adminer è un ottimo strumento, non è molto comodo per scrivere nuovi articoli del blog. Forse è il momento giusto per creare un semplice form che permetta di aggiungere nuovi articoli direttamente dall'applicazione. Facciamolo.

Cominciamo progettando l'interfaccia utente:

  1. Nella pagina principale aggiungiamo un link „Scrivi un nuovo articolo“.
  2. Questo link mostrerà un form con un campo per il titolo e una textarea per il contenuto dell'articolo.
  3. Quando clicchiamo il pulsante Salva, l'articolo verrà salvato nel database.

Più avanti aggiungeremo anche l'autenticazione e permetteremo di aggiungere nuovi articoli solo agli utenti connessi. Ma facciamolo dopo. Che codice dobbiamo scrivere ora perché tutto funzioni?

  1. Creare un nuovo presenter con il form per aggiungere gli articoli.
  2. Definire un callback che si attiverà dopo l'invio riuscito del form e salverà il nuovo articolo nel database.
  3. Creare un nuovo template per il form.
  4. Aggiungere il link al form nel template della pagina principale.

Nuovo presenter

Chiamiamo il nuovo presenter EditPresenter e salviamolo in app/Presentation/Edit/EditPresenter.php. Anche lui deve connettersi al database, quindi anche qui scriviamo un costruttore che richiede la connessione al database:

<?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,
	) {
	}
}

Form per salvare gli articoli

I form e i componenti li abbiamo già visti quando abbiamo aggiunto il supporto per i commenti. Se non è ancora chiaro, andate a rivedere come funzionano i form e i componenti, noi vi aspettiamo qui ;)

Aggiungete ora questo metodo all'EditPresenter:

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

	$form->addSubmit('send', 'Salva e pubblica');
	$form->onSuccess[] = $this->postFormSucceeded(...);

	return $form;
}

Salvare il nuovo articolo dal form

Proseguiamo aggiungendo il metodo gestore:

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

	$this->flashMessage('Articolo pubblicato con successo.', 'success');
	$this->redirect('Post:show', $post->id);
}

Solo una breve spiegazione: prende i valori dal form, li inserisce nel database, crea per l'utente un messaggio che dice che l'articolo è stato salvato con successo e reindirizza alla pagina in cui l'articolo è pubblicato, così potete vedere come appare.

Pagina per creare un nuovo articolo

Creiamo ora il template Edit/create.latte:

{block content}
<h1>Nuovo articolo</h1>

{control postForm}

Ormai dovrebbe essere tutto chiaro. L'ultima riga renderizza il form che abbiamo appena creato.

Potremmo creare anche il metodo renderCreate() corrispondente, ma non è necessario. Non dobbiamo prendere alcun dato dal database né passarlo al template, quindi il metodo sarebbe vuoto. In casi del genere il metodo non deve esistere affatto.

Probabilmente sapete già come aggiungere un link all'EditPresenter e alla sua azione create. Provate.

Basta aggiungere al file app/Presentation/Home/default.latte:

<a n:href="Edit:create">Scrivi un nuovo articolo</a>

Modificare gli articoli

Aggiungiamo ora la possibilità di modificare gli articoli esistenti. Sarà molto semplice. Abbiamo già il form postForm e lo possiamo usare anche per la modifica.

Aggiungiamo all'EditPresenter una nuova pagina edit:

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

	if (!$post) {
		$this->error('Articolo non trovato');
	}

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

E creiamo il template corrispondente Edit/edit.latte:

{block content}
<h1>Modifica articolo</h1>

{control postForm}

E aggiorniamo il metodo postFormSucceeded, che saprà sia aggiungere un nuovo articolo (come fa ora), sia modificare quelli esistenti:

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('Articolo pubblicato con successo.', 'success');
	$this->redirect('Post:show', $post->id);
}

Quando viene indicato il parametro id, significa che si sta modificando un articolo. In tal caso verifichiamo che l'articolo esista davvero e, in caso affermativo, lo aggiorniamo nel database. Se l'id non è indicato, significa che va aggiunto un nuovo articolo.

Ma da dove viene l'id? È il parametro passato al metodo renderEdit.

Ora potete aggiungere un link al template app/Presentation/Post/show.latte:

<a n:href="Edit:edit $post->id">Modifica questo articolo</a>

Il blog funziona, la gente commenta a ritmo serrato e per aggiungere nuovi articoli non dipendiamo più da Adminer. È del tutto indipendente e ci possono scrivere anche le persone comuni. Ma un momento, probabilmente non va bene che chiunque, e intendo davvero chiunque su internet, possa scrivere sul nostro blog. Serve una qualche forma di autenticazione, così che solo gli utenti connessi possano scrivere. La aggiungeremo nel prossimo capitolo.