Nette Documentation Preview

syntax
Model
*****

Man mano che la nostra applicazione cresce, scopriamo presto di dover eseguire operazioni simili sul database in punti diversi e in presenter diversi, per esempio ottenere gli ultimi articoli pubblicati. Se miglioriamo l'applicazione, per esempio aggiungendo agli articoli un flag che indica se sono bozze, dobbiamo anche rivedere tutti i punti in cui gli articoli vengono presi dal database e aggiungere una condizione `where` perché vengano selezionati solo gli articoli che non sono bozze.

A questo punto lavorare direttamente con il database non basta più e sarà più intelligente usare un nuovo metodo che restituisce gli articoli pubblicati. E quando più avanti aggiungeremo un'altra condizione (per esempio non mostrare gli articoli con data futura), modificheremo il nostro codice in un solo punto.

Metteremo il metodo nella classe `PostFacade` e lo chiameremo `getPublicArticles()`.

La nostra classe di modello `PostFacade` la creeremo nella directory `app/Model/`, perché si occupi dei nostri articoli:

```php .{file:app/Model/PostFacade.php}
<?php
namespace App\Model;

use Nette;

final class PostFacade
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	public function getPublicArticles()
	{
		return $this->database
			->table('posts')
			->where('created_at < ', new \DateTime)
			->order('created_at DESC');
	}
}
```

Nella classe ci facciamo passare l'[Explorer |api:Nette\Database\Explorer] del database tramite il costruttore. Sfruttiamo così la potenza del [container DI |dependency-injection:passing-dependencies].

Passiamo a `HomePresenter`, che modificheremo eliminando la dipendenza da `Nette\Database\Explorer` e sostituendola con una nuova dipendenza dalla nostra nuova classe.

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

use App\Model\PostFacade;
use Nette;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private PostFacade $facade,
	) {
	}

	public function renderDefault(): void
	{
		$this->template->posts = $this->facade
			->getPublicArticles()
			->limit(5);
	}
}
```

Nella sezione `use` abbiamo `App\Model\PostFacade`, quindi nel codice PHP possiamo abbreviare la notazione in `PostFacade`. Ci facciamo passare questo oggetto nel costruttore, lo scriviamo nella proprietà `$facade` e lo usiamo nel metodo `renderDefault`.

L'ultimo passo è insegnare al container DI a produrre questo oggetto. Di solito lo si fa aggiungendo una voce al file `config/services.neon` nella sezione `services`, indicando il nome completo della classe e i parametri del costruttore. Così viene registrato e l'oggetto si chiama poi **servizio**. Grazie alla magia dell'[autowiring |dependency-injection:autowiring] di solito non dobbiamo indicare i parametri del costruttore, perché la DI li riconosce e li passa da sé. Basterebbe quindi indicare solo il nome della classe:

```neon .{file:config/services.neon}
...

services:
	- App\Model\PostFacade
```

Neanche questa riga però dovete aggiungerla. Nella sezione `search` di `services.neon` è definito che tutte le classi che finiscono con `-Facade` oppure `-Factory` vengano trovate automaticamente dalla DI, ed è il caso anche di `PostFacade`.


Riepilogo
=========

La classe `PostFacade` chiede nel proprio costruttore `Nette\Database\Explorer` e, poiché questa classe è registrata nel container DI, il container crea questa istanza e la passa. La DI crea così per noi un'istanza di `PostFacade` e la passa nel costruttore alla classe `HomePresenter`, che l'ha richiesta. È come una matrioska. :) Ognuno dice solo che cosa vuole e non gli importa dove e come venga creato. Della creazione si occupa il container DI.

.[note]
Qui potete leggere di più sulla [dependency injection |dependency-injection:introduction] e sulla [configurazione |nette:configuring].

{{priority: -1}}

Model

Man mano che la nostra applicazione cresce, scopriamo presto di dover eseguire operazioni simili sul database in punti diversi e in presenter diversi, per esempio ottenere gli ultimi articoli pubblicati. Se miglioriamo l'applicazione, per esempio aggiungendo agli articoli un flag che indica se sono bozze, dobbiamo anche rivedere tutti i punti in cui gli articoli vengono presi dal database e aggiungere una condizione where perché vengano selezionati solo gli articoli che non sono bozze.

A questo punto lavorare direttamente con il database non basta più e sarà più intelligente usare un nuovo metodo che restituisce gli articoli pubblicati. E quando più avanti aggiungeremo un'altra condizione (per esempio non mostrare gli articoli con data futura), modificheremo il nostro codice in un solo punto.

Metteremo il metodo nella classe PostFacade e lo chiameremo getPublicArticles().

La nostra classe di modello PostFacade la creeremo nella directory app/Model/, perché si occupi dei nostri articoli:

<?php
namespace App\Model;

use Nette;

final class PostFacade
{
	public function __construct(
		private Nette\Database\Explorer $database,
	) {
	}

	public function getPublicArticles()
	{
		return $this->database
			->table('posts')
			->where('created_at < ', new \DateTime)
			->order('created_at DESC');
	}
}

Nella classe ci facciamo passare l'Explorer del database tramite il costruttore. Sfruttiamo così la potenza del container DI.

Passiamo a HomePresenter, che modificheremo eliminando la dipendenza da Nette\Database\Explorer e sostituendola con una nuova dipendenza dalla nostra nuova classe.

<?php
namespace App\Presentation\Home;

use App\Model\PostFacade;
use Nette;

final class HomePresenter extends Nette\Application\UI\Presenter
{
	public function __construct(
		private PostFacade $facade,
	) {
	}

	public function renderDefault(): void
	{
		$this->template->posts = $this->facade
			->getPublicArticles()
			->limit(5);
	}
}

Nella sezione use abbiamo App\Model\PostFacade, quindi nel codice PHP possiamo abbreviare la notazione in PostFacade. Ci facciamo passare questo oggetto nel costruttore, lo scriviamo nella proprietà $facade e lo usiamo nel metodo renderDefault.

L'ultimo passo è insegnare al container DI a produrre questo oggetto. Di solito lo si fa aggiungendo una voce al file config/services.neon nella sezione services, indicando il nome completo della classe e i parametri del costruttore. Così viene registrato e l'oggetto si chiama poi servizio. Grazie alla magia dell'autowiring di solito non dobbiamo indicare i parametri del costruttore, perché la DI li riconosce e li passa da sé. Basterebbe quindi indicare solo il nome della classe:

...

services:
	- App\Model\PostFacade

Neanche questa riga però dovete aggiungerla. Nella sezione search di services.neon è definito che tutte le classi che finiscono con -Facade oppure -Factory vengano trovate automaticamente dalla DI, ed è il caso anche di PostFacade.

La classe PostFacade chiede nel proprio costruttore Nette\Database\Explorer e, poiché questa classe è registrata nel container DI, il container crea questa istanza e la passa. La DI crea così per noi un'istanza di PostFacade e la passa nel costruttore alla classe HomePresenter, che l'ha richiesta. È come una matrioska. :) Ognuno dice solo che cosa vuole e non gli importa dove e come venga creato. Della creazione si occupa il container DI.

Qui potete leggere di più sulla dependency injection e sulla configurazione.