Nette Documentation Preview

syntax
Home page del blog
******************

.[perex]
Creiamo la pagina iniziale che mostra i post recenti.


Prima di iniziare, è necessario conoscere almeno alcune nozioni di base sul modello di progettazione Model-View-Presenter (simile a MVC((Model-View-Controller)):

- **Modello** - livello di manipolazione dei dati. È completamente separato dal resto dell'applicazione. Comunica solo con i presentatori.

- **Vista** - livello di definizione del front-end. Rende i dati richiesti all'utente utilizzando i modelli.

- **Presenter** (o Controller) - un livello di connessione. Il presentatore collega Modello e Vista. Gestisce le richieste, chiede i dati al Modello e li passa alla Vista corrente.


Nel caso di un'applicazione molto semplice come il nostro blog, il livello Model consisterà in realtà solo di query al database stesso: non abbiamo bisogno di codice PHP aggiuntivo per questo. Dobbiamo solo creare i livelli Presenter e View. In Nette, ogni Presentatore ha le proprie Viste, quindi continueremo con entrambe contemporaneamente.


Creare il database con Adminer .[#toc-creating-the-database-with-adminer]
=========================================================================

Per memorizzare i dati, utilizzeremo il database MySQL, perché è la scelta più comune tra gli sviluppatori web. Ma se non vi piace, siete liberi di usare un database di vostra scelta.

Prepariamo il database che memorizzerà i post del nostro blog. Possiamo iniziare in modo molto semplice, con una sola tabella per i post.

Per creare il database possiamo scaricare [Adminer |https://www.adminer.org], oppure utilizzare un altro strumento per la gestione dei database.


Apriamo Adminer e creiamo un nuovo database chiamato `quickstart`.

Creiamo una nuova tabella denominata `posts` e aggiungiamo le seguenti colonne:
- `id` int, cliccare su autoincremento (AI)
- `title` varchar, lunghezza 255
- `content` testo
- `created_at` timestamp

L'aspetto dovrebbe essere il seguente:

[* adminer-posts.webp *]

```sql
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;
```

.[caution]
È molto importante utilizzare la memorizzazione della tabella **InnoDB**. Il motivo lo si vedrà più avanti. Per ora, scegliere questo e inviare. Ora si può premere Salva.

Provate ad aggiungere alcuni post del blog di esempio prima di implementare la possibilità di aggiungere nuovi post direttamente dalla nostra applicazione.

```sql
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);
```


Connessione al database .[#toc-connecting-to-the-database]
==========================================================

Ora, quando il database è stato creato e abbiamo alcuni post al suo interno, è il momento giusto per visualizzarli sulla nostra nuova pagina.

Per prima cosa, dobbiamo indicare alla nostra applicazione quale database utilizzare. La configurazione della connessione al database è memorizzata in `config/common.neon`. Impostare la connessione DSN((Data Source Name)) e le credenziali. Dovrebbe essere così:

```neon .{file:config/common.neon}
database:
	dsn: 'mysql:host=127.0.0.1;dbname=quickstart'
	user: *enter user name*
	password: *enter password here*
```

.[note]
Fare attenzione all'indentazione durante la modifica di questo file. Il [formato NEON |neon:format] accetta sia spazi che tabulazioni, ma non entrambi insieme! Il file di configurazione del progetto Web utilizza le tabulazioni come impostazione predefinita.


Iniettare la connessione al database .[#toc-injecting-the-database-connection]
==============================================================================

Il presentatore `HomePresenter`, che elencherà gli articoli, ha bisogno di una connessione al database. Per riceverla, scrivere un costruttore come questo:

```php .{file:app/UI/Home/HomePresenter.php}
<?php
namespace App\UI\Home;

use Nette;

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

	// ...
}
```


Caricamento dei post dal database .[#toc-loading-posts-from-the-database]
=========================================================================

Ora recuperiamo i post dal database e passiamoli al template, che poi renderà il codice HTML. A questo serve il cosiddetto metodo *render*:

```php .{file:app/UI/Home/HomePresenter.php}
public function renderDefault(): void
{
	$this->template->posts = $this->database
		->table('posts')
		->order('created_at DESC')
		->limit(5);
}
```

Il presentatore ha ora un metodo di render `renderDefault()` che passa i dati a una vista chiamata `default`. I modelli del presentatore si trovano in `app/UI/{PresenterName}/{viewName}.latte`, quindi in questo caso il modello si trova in `app/UI/Home/default.latte`. Nel modello, è ora disponibile una variabile chiamata `$posts`, che contiene i post del database.


Modello .[#toc-template]
========================

Esiste un modello generico per l'intera pagina (chiamato *layout*, con intestazione, fogli di stile, piè di pagina, ...) e poi modelli specifici per ogni vista (ad esempio per visualizzare l'elenco dei post del blog), che possono sovrascrivere alcune parti del modello di layout.

Per impostazione predefinita, il modello di layout si trova in `templates/@layout.latte`, che contiene:

```latte .{file:app/UI/@layout.latte}
...
{include content}
...
```

`{include content}` inserisce un blocco chiamato `content` nel modello principale. È possibile definirlo nei modelli di ciascuna vista. In questo caso, modificheremo il file `Home/default.latte` in questo modo:

```latte .{file:app/UI/Home/default.latte}
{block content}
	Hello World
{/block}
```

Definisce il [blocco |latte:tags#block]*content*, che sarà inserito nel layout. Se si aggiorna il browser, si vedrà una pagina con il testo "Hello world" (nel codice sorgente anche con l'intestazione e il piè di pagina HTML definiti in `@layout.latte`).

Visualizziamo i post del blog: modificheremo il template in questo modo:

```latte .{file:app/UI/Home/default.latte}
{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}
```

Se si aggiorna il browser, si vedrà l'elenco dei post del blog. L'elenco non è molto elegante o colorato, quindi sentitevi liberi di aggiungere qualche [CSS brillante |https://github.com/nette-examples/quickstart/blob/v4.0/www/css/style.css] a `www/css/style.css` e di collegarlo a un layout:

```latte .{file:app/UI/@layout.latte}
	...
	<link rel="stylesheet" href="{$basePath}/css/style.css">
</head>
...
```

Il tag `{foreach}` itera tutti i post passati al template nella variabile `$posts` e mostra un pezzo di codice HTML per ogni post. Proprio come farebbe un codice PHP.

L'elemento `|date` è chiamato filtro. I filtri sono usati per formattare l'output. Questo particolare filtro converte una data (per esempio `2013-04-12`) nella sua forma più leggibile (`12. 4. 2013`). Il filtro `|truncate` tronca la stringa alla lunghezza massima specificata e aggiunge un'ellissi alla fine se la stringa è troncata. Trattandosi di un'anteprima, non ha senso visualizzare il contenuto completo dell'articolo. Altri filtri predefiniti sono disponibili [nella documentazione |latte:filters] o, se necessario, è possibile crearne di propri.

Un'altra cosa. Possiamo rendere il codice un po' più corto e quindi più semplice. Possiamo sostituire i tag *Latte* con *n:attributi* in questo modo:

```latte .{file:app/UI/Home/default.latte}
{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}
```

`n:foreach`, semplicemente avvolge il *div* con un blocco *foreach* (fa esattamente la stessa cosa del blocco di codice precedente).


Sintesi .[#toc-summary]
=======================

Abbiamo un database MySQL molto semplice con alcuni post del blog. L'applicazione si connette al database e visualizza un semplice elenco dei post.

{{priority: -1}}
{{sitename: Nette Quickstart}}

Home page del blog

Creiamo la pagina iniziale che mostra i post recenti.

Prima di iniziare, è necessario conoscere almeno alcune nozioni di base sul modello di progettazione Model-View-Presenter (simile a MVC:

  • Modello – livello di manipolazione dei dati. È completamente separato dal resto dell'applicazione. Comunica solo con i presentatori.
  • Vista – livello di definizione del front-end. Rende i dati richiesti all'utente utilizzando i modelli.
  • Presenter (o Controller) – un livello di connessione. Il presentatore collega Modello e Vista. Gestisce le richieste, chiede i dati al Modello e li passa alla Vista corrente.

Nel caso di un'applicazione molto semplice come il nostro blog, il livello Model consisterà in realtà solo di query al database stesso: non abbiamo bisogno di codice PHP aggiuntivo per questo. Dobbiamo solo creare i livelli Presenter e View. In Nette, ogni Presentatore ha le proprie Viste, quindi continueremo con entrambe contemporaneamente.

Creare il database con Adminer

Per memorizzare i dati, utilizzeremo il database MySQL, perché è la scelta più comune tra gli sviluppatori web. Ma se non vi piace, siete liberi di usare un database di vostra scelta.

Prepariamo il database che memorizzerà i post del nostro blog. Possiamo iniziare in modo molto semplice, con una sola tabella per i post.

Per creare il database possiamo scaricare Adminer, oppure utilizzare un altro strumento per la gestione dei database.

Apriamo Adminer e creiamo un nuovo database chiamato quickstart.

Creiamo una nuova tabella denominata posts e aggiungiamo le seguenti colonne:

  • id int, cliccare su autoincremento (AI)
  • title varchar, lunghezza 255
  • content testo
  • created_at timestamp

L'aspetto dovrebbe essere il seguente:

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;

È molto importante utilizzare la memorizzazione della tabella InnoDB. Il motivo lo si vedrà più avanti. Per ora, scegliere questo e inviare. Ora si può premere Salva.

Provate ad aggiungere alcuni post del blog di esempio prima di implementare la possibilità di aggiungere nuovi post direttamente dalla nostra applicazione.

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);

Connessione al database

Ora, quando il database è stato creato e abbiamo alcuni post al suo interno, è il momento giusto per visualizzarli sulla nostra nuova pagina.

Per prima cosa, dobbiamo indicare alla nostra applicazione quale database utilizzare. La configurazione della connessione al database è memorizzata in config/common.neon. Impostare la connessione DSN e le credenziali. Dovrebbe essere così:

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

Fare attenzione all'indentazione durante la modifica di questo file. Il formato NEON accetta sia spazi che tabulazioni, ma non entrambi insieme! Il file di configurazione del progetto Web utilizza le tabulazioni come impostazione predefinita.

Iniettare la connessione al database

Il presentatore HomePresenter, che elencherà gli articoli, ha bisogno di una connessione al database. Per riceverla, scrivere un costruttore come questo:

<?php
namespace App\UI\Home;

use Nette;

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

	// ...
}

Caricamento dei post dal database

Ora recuperiamo i post dal database e passiamoli al template, che poi renderà il codice HTML. A questo serve il cosiddetto metodo render:

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

Il presentatore ha ora un metodo di render renderDefault() che passa i dati a una vista chiamata default. I modelli del presentatore si trovano in app/UI/{PresenterName}/{viewName}.latte, quindi in questo caso il modello si trova in app/UI/Home/default.latte. Nel modello, è ora disponibile una variabile chiamata $posts, che contiene i post del database.

Modello

Esiste un modello generico per l'intera pagina (chiamato layout, con intestazione, fogli di stile, piè di pagina, …) e poi modelli specifici per ogni vista (ad esempio per visualizzare l'elenco dei post del blog), che possono sovrascrivere alcune parti del modello di layout.

Per impostazione predefinita, il modello di layout si trova in templates/@layout.latte, che contiene:

...
{include content}
...

{include content} inserisce un blocco chiamato content nel modello principale. È possibile definirlo nei modelli di ciascuna vista. In questo caso, modificheremo il file Home/default.latte in questo modo:

{block content}
	Hello World
{/block}

Definisce il bloccocontent, che sarà inserito nel layout. Se si aggiorna il browser, si vedrà una pagina con il testo „Hello world“ (nel codice sorgente anche con l'intestazione e il piè di pagina HTML definiti in @layout.latte).

Visualizziamo i post del blog: modificheremo il template in questo modo:

{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}

Se si aggiorna il browser, si vedrà l'elenco dei post del blog. L'elenco non è molto elegante o colorato, quindi sentitevi liberi di aggiungere qualche CSS brillante a www/css/style.css e di collegarlo a un layout:

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

Il tag {foreach} itera tutti i post passati al template nella variabile $posts e mostra un pezzo di codice HTML per ogni post. Proprio come farebbe un codice PHP.

L'elemento |date è chiamato filtro. I filtri sono usati per formattare l'output. Questo particolare filtro converte una data (per esempio 2013-04-12) nella sua forma più leggibile (12. 4. 2013). Il filtro |truncate tronca la stringa alla lunghezza massima specificata e aggiunge un'ellissi alla fine se la stringa è troncata. Trattandosi di un'anteprima, non ha senso visualizzare il contenuto completo dell'articolo. Altri filtri predefiniti sono disponibili nella documentazione o, se necessario, è possibile crearne di propri.

Un'altra cosa. Possiamo rendere il codice un po' più corto e quindi più semplice. Possiamo sostituire i tag Latte con n:attributi in questo modo:

{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}

n:foreach, semplicemente avvolge il div con un blocco foreach (fa esattamente la stessa cosa del blocco di codice precedente).

Sintesi

Abbiamo un database MySQL molto semplice con alcuni post del blog. L'applicazione si connette al database e visualizza un semplice elenco dei post.