Modello
Man mano che l'applicazione cresce, ci accorgeremo presto che in diversi punti, in diversi presenter, abbiamo bisogno di eseguire operazioni simili con il database. Ad esempio, ottenere gli articoli pubblicati più di recente. Se miglioriamo l'applicazione, ad esempio aggiungendo un flag agli articoli per indicare se sono in bozza, dobbiamo poi passare attraverso tutti i punti dell'applicazione in cui gli articoli vengono recuperati dal database e aggiungere una condizione where per selezionare solo gli articoli non in bozza.
In quel momento, il lavoro diretto con il database diventa insufficiente e sarà più pratico aiutarci con una nuova funzione che ci restituirà gli articoli pubblicati. E quando in seguito aggiungeremo un'altra condizione, ad esempio che non devono essere visualizzati articoli con data futura, modificheremo il codice solo in un punto.
Posizioneremo la funzione ad esempio nella classe PostFacade
e la chiameremo getPublicArticles()
.
Nella directory app/Model/
creiamo la nostra classe modello PostFacade
, che si occuperà degli
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, tramite il costruttore, ci facciamo passare l'Explorer del database. Sfruttiamo così la potenza del container DI.
Passiamo a HomePresenter
, che modificheremo in modo da eliminare la dipendenza da
Nette\Database\Explorer
e sostituirla con la 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 possiamo abbreviare la scrittura nel codice PHP in
PostFacade
. Richiediamo questo oggetto nel costruttore, lo scriviamo nella proprietà $facade
e lo
usiamo nel metodo renderDefault.
Resta l'ultimo passo, ovvero insegnare al container DI a produrre questo oggetto. Di solito si fa aggiungendo un trattino nella
sezione services
del file config/services.neon
, indicando il nome completo della classe e i parametri
del costruttore. In questo modo la registriamo e l'oggetto viene quindi chiamato servizio. Grazie alla magia chiamata autowiring di solito non dobbiamo specificare i parametri del
costruttore, perché DI li riconosce e li passa da solo. Basterebbe quindi indicare solo il nome della classe:
...
services:
- App\Model\PostFacade
Tuttavia, non è nemmeno necessario aggiungere questa riga. Nella sezione search
all'inizio di
services.neon
è definito che tutte le classi che terminano con la parola -Facade
o
-Factory
vengono trovate automaticamente da DI, il che è anche il caso di PostFacade
.
Riepilogo
La classe PostFacade
richiede nel costruttore il passaggio di Nette\Database\Explorer
e poiché
questa classe è registrata nel container DI, il container crea questa istanza e la passa. DI crea così per noi l'istanza di
PostFacade
e la passa nel costruttore alla classe HomePresenter, che l'ha richiesta. Una specie di matrioska. :)
Tutti dicono solo cosa vogliono e non si preoccupano di dove e come viene creato qualcosa. Della creazione si occupa il
container DI.
Qui potete leggere di più sulla dependency injection e sulla configurazione.