Fabbriche generate
Nette DI può generare automaticamente il codice di fabbrica basato sull'interfaccia, evitando così di scrivere codice.
Un factory è una classe che crea e configura gli oggetti. Pertanto, passa anche le loro dipendenze. Non bisogna confondersi con il design pattern metodo di fabbrica, che descrive un modo specifico di usare i factory e non è correlato a questo argomento.
Abbiamo mostrato l'aspetto di una fabbrica di questo tipo nel capitolo introduttivo:
Nette DI può generare automaticamente il codice del factory. Tutto ciò che si deve fare è creare un'interfaccia e Nette DI
genererà un'implementazione. L'interfaccia deve avere esattamente un metodo chiamato create
e dichiarare un tipo di
ritorno:
Quindi il factory ArticleFactory
ha un metodo create
che crea oggetti Article
. La classe
Article
potrebbe avere il seguente aspetto, ad esempio:
Aggiungere il factory al file di configurazione:
Nette DI genererà l'implementazione del factory corrispondente.
Pertanto, nel codice che utilizza il factory, si richiede l'oggetto per interfaccia e Nette DI utilizza l'implementazione generata:
Fabbrica parametrizzata
Il metodo factory create
può accettare parametri, che poi passa al costruttore. Per esempio, aggiungiamo l'ID
dell'autore di un articolo alla classe Article
:
Aggiungeremo anche il parametro al factory:
Poiché il parametro nel costruttore e quello nel factory hanno lo stesso nome, Nette DI li passerà automaticamente.
Definizione avanzata
La definizione può essere scritta anche in forma multilinea utilizzando il tasto implement
:
Quando si scrive in questo modo più lungo, è possibile fornire argomenti aggiuntivi per il costruttore nella chiave
arguments
e configurazioni aggiuntive usando setup
, proprio come per i servizi normali.
Esempio: se il metodo create()
non accettasse il parametro $authorId
, si potrebbe specificare nella
configurazione un valore fisso da passare al costruttore Article
:
Oppure, al contrario, se create()
accettasse il parametro $authorId
, ma non facesse parte del
costruttore e fosse passato dal metodo Article::setAuthorId()
, faremmo riferimento ad esso nella sezione
setup
:
Accessore
Oltre ai factory, Nette può anche generare i cosiddetti accessor. L'accessor è un oggetto con il metodo get()
che restituisce un particolare servizio dal contenitore DI. Più chiamate a get()
restituiranno sempre la stessa
istanza.
Gli accessor portano il lazy-loading alle dipendenze. Abbiamo una classe che registra gli errori in un database speciale. Se la
connessione al database fosse passata come dipendenza nel suo costruttore, la connessione dovrebbe essere sempre creata, anche se
verrebbe usata solo raramente, quando appare un errore, quindi la connessione rimarrebbe per lo più inutilizzata. Invece, la
classe può passare un accessor e quando viene chiamato il suo metodo get()
, solo allora viene creato l'oggetto
database:
Come creare un accessor? Scrivete solo un'interfaccia e Nette DI genererà l'implementazione. L'interfaccia deve avere
esattamente un metodo chiamato get
e deve dichiarare il tipo di ritorno:
Aggiungete l'accessor al file di configurazione insieme alla definizione del servizio che l'accessor restituirà:
L'accessor restituisce un servizio di tipo PDO
e poiché esiste un solo servizio di questo tipo nella
configurazione, l'accessor lo restituirà. Con più servizi configurati di quel tipo, si può specificare quale deve essere
restituito usando il suo nome, per esempio - PDOAccessor(@db1)
.
Multifactory/Accessor
Finora, i factory e gli accessor potevano creare o restituire un solo oggetto. È possibile creare anche una multifactory
combinata con un accessor. L'interfaccia di questa classe multifactory può essere composta da più metodi chiamati
create<name>()
e get<name>()
ad esempio:
Invece di passare più factory e accessor generati, si può passare un solo multifactory complesso.
In alternativa, si può usare get()
con un parametro invece di più metodi:
In questo caso, MultiFactory::getArticle()
fa la stessa cosa di MultiFactoryAlt::get('article')
.
Tuttavia, la sintassi alternativa presenta alcuni svantaggi. Non è chiaro quali valori di $name
siano supportati e
il tipo di ritorno non può essere specificato nell'interfaccia quando si usano più valori diversi di $name
.
Definizione con un elenco
Questo modo può essere usato per definire una fabbrica multipla nella configurazione:
Oppure, nella definizione del factory, si può fare riferimento a servizi esistenti usando un riferimento:
Definizione con tag
Un'altra opzione per definire una multifactory è quella di usare i tag: