Configurazione del container DI

Panoramica delle opzioni di configurazione del container DI di Nette.

File di configurazione

Il container DI di Nette si governa facilmente con i file di configurazione. Di norma si scrivono nel formato NEON. Consigliamo di usare editor con supporto per questo formato.

 decorator: 	Decorator
di: Container DI
extensions: Installazione di altre estensioni DI
includes: Inclusione di file
parameters: Parametri
search: Registrazione automatica dei servizi
services: Servizi

Per scrivere una stringa che contiene il carattere %, dovete effettuare l'escape raddoppiandolo in %%.

Parametri

Nella configurazione potete definire parametri, che si possono poi usare all'interno delle definizioni dei servizi. Questo vi permette di rendere più chiara la configurazione o di centralizzare i valori che potrebbero cambiare.

parameters:
	dsn: 'mysql:host=127.0.0.1;dbname=test'
	user: root
	password: secret

Facciamo riferimento al parametro dsn in qualsiasi punto della configurazione con la notazione %dsn%. I parametri si possono usare anche dentro le stringhe, come '%wwwDir%/images'.

I parametri non devono essere per forza solo stringhe o numeri: possono contenere anche array:

parameters:
	mailer:
		host: smtp.example.com
		secure: ssl
		user: franta@gmail.com
	languages: [cs, en, de]

Facciamo riferimento a una chiave specifica come %mailer.user%.

Se il vostro codice (per esempio una classe) ha bisogno del valore di un parametro, passatelo alla classe. Per esempio nel costruttore. Non esiste un oggetto di configurazione globale a cui le classi possano chiedere i valori dei parametri. Sarebbe una violazione del principio della dependency injection.

Servizi

Vedi il capitolo dedicato.

Decorator

Come modificare in un colpo solo più servizi di un certo tipo? Per esempio, come chiamare un determinato metodo su tutti i presenter che ereditano da una certa classe base? A questo serve il decorator.

decorator:
	# per tutti i servizi che sono istanze di questa classe o interfaccia
	App\Presentation\BasePresenter:
		setup:
			- setProjectId(10)       # chiama questo metodo
			- $absoluteUrls = true   # e imposta la variabile

I decorator si possono usare anche per impostare i tag o per attivare la modalità inject.

decorator:
	InjectableInterface:
		tags: [mytag: 1]
		inject: true

DI

Impostazioni tecniche del container DI.

di:
	# mostrare il DIC nella Tracy Bar?
	debugger: ...        # (bool) di norma per rilevamento automatico (attivo quando Tracy è presente)

	# tipi di parametro a cui non applicare mai l'autowiring
	excluded: ...        # (string[])

	# attivare la creazione pigra dei servizi?
	lazy: ...            # (bool) di norma false

	# la classe da cui eredita il container DI
	parentClass: ...     # (string) di norma Nette\DI\Container

Servizi pigri

Impostare lazy: true attiva la creazione pigra (differita) dei servizi. Significa che i servizi non vengono creati davvero nel momento in cui li si chiede al container DI, ma solo al momento del loro primo uso. Questo può accelerare l'avvio dell'applicazione e ridurre l'uso della memoria, perché vengono creati solo i servizi effettivamente necessari a una determinata richiesta.

Per un servizio specifico la creazione pigra si può regolare.

Gli oggetti pigri si possono usare solo per le classi definite dall'utente, non per le classi interne di PHP. Richiede PHP 8.4 o successivo.

Esportazione dei metadati

La classe del container DI contiene anche molti metadati. Potete ridurne la dimensione riducendo l'esportazione dei metadati.

di:
	export:
		# esportare i parametri?
		parameters: false   # (bool) di norma true

		# esportare i tag e quali?
		tags:               # (string[]|bool) di norma tutti
			- event.subscriber

		# esportare i dati per l'autowiring e quali?
		types:              # (string[]|bool) di norma tutti
			- Nette\Database\Connection
			- Symfony\Component\Console\Application

Se non usate $container->getParameters(), potete disattivare l'esportazione dei parametri. Potete inoltre esportare solo i tag che usate davvero per ottenere i servizi con $container->findByTag(...). Se non chiamate affatto questo metodo, potete disattivare completamente l'esportazione dei tag con false.

Potete ridurre notevolmente i metadati per l'autowiring elencando solo le classi che chiedete davvero con $container->getByType(). Anche qui, se non chiamate questo metodo (o lo chiamate solo nel file di bootstrap, per esempio per ottenere Nette\Application\Application), potete disattivare completamente l'esportazione dei tipi con false.

Estensioni

Registrazione di ulteriori estensioni DI. Ecco come aggiungete, per esempio, l'estensione DI Dibi\Bridges\Nette\DibiExtension3 con il nome dibi:

extensions:
	dibi: Dibi\Bridges\Nette\DibiExtension3

La configurate poi nella sezione dibi:

dibi:
	host: localhost

Come estensione potete aggiungere anche una classe con parametri:

extensions:
	application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, [%appDir%], %tempDir%/cache)

Inclusione di file

Ulteriori file di configurazione si possono includere nella sezione includes:

includes:
	- parameters.php
	- services.neon
	- presenters.neon

Il nome parameters.php non è un errore di battitura: la configurazione si può scrivere anche in un file PHP che la restituisce come array:

<?php
return [
	'database' => [
		'main' => [
			'dsn' => 'sqlite::memory:',
		],
	],
];

Se in più file di configurazione compaiono elementi con le stesse chiavi, essi verranno sovrascritti oppure, nel caso degli array, uniti. Un file incluso più tardi ha priorità maggiore rispetto al precedente. Il file in cui è indicata la sezione includes ha priorità maggiore rispetto ai file inclusi al suo interno.

La registrazione automatica dei servizi nel container DI semplifica notevolmente lo sviluppo. Nette aggiunge automaticamente al container i presenter, ma potete aggiungervi facilmente anche qualsiasi altra classe.

Basta indicare in quali directory (e sottodirectory) cercare le classi:

search:
	-	in: %appDir%/Forms
	-	in: %appDir%/Model

Se vi serve una sola regola di ricerca, potete omettere l'elenco e scriverne le chiavi direttamente sotto search:

search:
	in: %appDir%

Di norma, però, non vogliamo aggiungere assolutamente tutte le classi e le interfacce, quindi possiamo filtrarle:

search:
	-	in: %appDir%/Forms

		# filtraggio per nome di file (string|string[])
		files:
			- *Factory.php

		# filtraggio per nome di classe (string|string[])
		classes:
			- *Factory

Oppure possiamo selezionare le classi che ereditano o implementano almeno una delle classi elencate:

search:
	-	in: %appDir%
		extends:
			- App\*Form
		implements:
			- App\*FormInterface

Potete definire anche regole di esclusione, con maschere di nomi di classe o di antenati. Se una classe corrisponde a una regola di esclusione, non verrà aggiunta al container DI:

search:
	-	in: %appDir%
		exclude:
			files: ...
			classes: ...
			extends: ...
			implements: ...

A tutti i servizi registrati automaticamente si possono assegnare dei tag:

search:
	-	in: %appDir%
		tags: ...

Oltre alle classi, la ricerca registra anche le interfacce che hanno un unico metodo create() o get(), come factory o accessor generati. Le classi per cui nel container è già registrato un servizio dello stesso tipo vengono saltate, così non si creano duplicati.

Unione

Se in più file di configurazione compaiono elementi con le stesse chiavi, essi verranno sovrascritti oppure, nel caso degli array, uniti. Il file incluso più tardi ha priorità maggiore rispetto al precedente.

config1.neon config2.neon risultato
items:
	- 1
	- 2
items:
	- 3
items:
	- 1
	- 2
	- 3

Per gli array l'unione si può impedire aggiungendo un punto esclamativo dopo il nome della chiave:

config1.neon config2.neon risultato
items:
	- 1
	- 2
items!:
	- 3
items:
	- 3
versione: 3.x