Konfiguration des DI-Containers

Übersicht über die Konfigurationsoptionen für den Nette DI Container.

Konfigurationsdatei

Der Nette DI Container lässt sich leicht über Konfigurationsdateien steuern. Diese werden normalerweise im NEON-Format geschrieben. Zur Bearbeitung empfehlen wir Editoren mit Unterstützung für dieses Format.

 decorator: 	Decorator
di: DI-Container
extensions: Installation weiterer DI-Erweiterungen
includes: Einbinden von Dateien
parameters: Parameter
search: Automatische Registrierung von Diensten
services: Dienste

Um eine Zeichenkette zu schreiben, die das Zeichen % enthält, müssen Sie es durch Verdoppelung auf %% escapen.

Parameter

In der Konfiguration können Sie Parameter definieren, die dann als Teil der Dienstdefinitionen verwendet werden können. Dadurch können Sie die Konfiguration übersichtlicher gestalten oder Werte vereinheitlichen und ausgliedern, die sich ändern werden.

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

Auf den Parameter dsn verweisen wir überall in der Konfiguration mit der Schreibweise %dsn%. Parameter können auch innerhalb von Zeichenketten wie '%wwwDir%/images' verwendet werden.

Parameter müssen nicht nur Zeichenketten oder Zahlen sein, sie können auch Arrays enthalten:

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

Auf einen bestimmten Schlüssel verweisen wir als %mailer.user%.

Wenn Sie in Ihrem Code, beispielsweise in einer Klasse, den Wert eines Parameters ermitteln müssen, übergeben Sie ihn an diese Klasse. Zum Beispiel im Konstruktor. Es gibt kein globales Objekt, das die Konfiguration repräsentiert, bei dem Klassen Parameterwerte abfragen könnten. Das würde gegen das Prinzip der Dependency Injection verstoßen.

Dienste

Siehe separates Kapitel.

Decorator

Wie kann man alle Dienste eines bestimmten Typs massenhaft ändern? Zum Beispiel eine bestimmte Methode bei allen Presentern aufrufen, die von einem bestimmten gemeinsamen Vorfahren erben? Dafür gibt es den Decorator.

decorator:
	# für alle Dienste, die Instanzen dieser Klasse oder Schnittstelle sind
	App\Presentation\BasePresenter:
		setup:
			- setProjectId(10)       # rufe diese Methode auf
			- $absoluteUrls = true   # und setze die Variable

Der Decorator kann auch verwendet werden, um Tags zu setzen oder den inject-Modus zu aktivieren.

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

DI

Technische Einstellungen des DI-Containers.

di:
	# DIC in der Tracy Bar anzeigen?
	debugger: ...        # (bool) Standard ist true

	# Parametertypen, die niemals autowired werden sollen
	excluded: ...        # (string[])

	# lazy Erstellung von Diensten erlauben?
	lazy: ...            # (bool) Standard ist false

	# Klasse, von der der DI-Container erbt
	parentClass: ...     # (string) Standard ist Nette\DI\Container

Lazy Dienste

Die Einstellung lazy: true aktiviert die lazy (verzögerte) Erstellung von Diensten. Das bedeutet, dass Dienste nicht tatsächlich erstellt werden, wenn wir sie vom DI-Container anfordern, sondern erst im Moment ihrer ersten Verwendung. Dies kann den Start der Anwendung beschleunigen und den Speicherbedarf reduzieren, da nur die Dienste erstellt werden, die im jeweiligen Request tatsächlich benötigt werden.

Für einen bestimmten Dienst kann die lazy Erstellung geändert werden.

Lazy Objekte können nur für benutzerdefinierte Klassen verwendet werden, nicht für interne PHP-Klassen. Erfordert PHP 8.4 oder neuer.

Export von Metadaten

Die DI-Container-Klasse enthält auch viele Metadaten. Sie können sie verkleinern, indem Sie den Export von Metadaten reduzieren.

di:
	export:
		# Parameter exportieren?
		parameters: false   # (bool) Standard ist true

		# Tags exportieren und welche?
		tags:               # (string[]|bool) Standard sind alle
			- event.subscriber

		# Daten für Autowiring exportieren und welche?
		types:              # (string[]|bool) Standard sind alle
			- Nette\Database\Connection
			- Symfony\Component\Console\Application

Wenn Sie das Array $container->getParameters() nicht verwenden, können Sie den Parameter-Export deaktivieren. Weiterhin können Sie nur die Tags exportieren, über die Sie Dienste mit der Methode $container->findByTag(...) abrufen. Wenn Sie die Methode überhaupt nicht aufrufen, können Sie den Tag-Export mit false vollständig deaktivieren.

Sie können die Metadaten für Autowiring erheblich reduzieren, indem Sie die Klassen angeben, die Sie als Parameter der Methode $container->getByType() verwenden. Und wiederum, wenn Sie die Methode überhaupt nicht aufrufen (bzw. nur im Bootstrap, um Nette\Application\Application zu erhalten), können Sie den Export mit false vollständig deaktivieren.

Erweiterungen

Registrierung weiterer DI-Erweiterungen. Auf diese Weise fügen wir z. B. die DI-Erweiterung Dibi\Bridges\Nette\DibiExtension22 unter dem Namen dibi hinzu

extensions:
	dibi: Dibi\Bridges\Nette\DibiExtension22

Anschließend konfigurieren wir sie im Abschnitt dibi:

dibi:
	host: localhost

Als Erweiterung kann auch eine Klasse hinzugefügt werden, die Parameter hat:

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

Dateien einbinden

Weitere Konfigurationsdateien können wir im Abschnitt includes einfügen:

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

Der Name parameters.php ist kein Tippfehler, die Konfiguration kann auch in einer PHP-Datei geschrieben werden, die sie als Array zurückgibt:

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

Wenn in Konfigurationsdateien Elemente mit denselben Schlüsseln erscheinen, werden sie überschrieben oder im Falle von Arrays zusammengeführt. Eine später eingebundene Datei hat eine höhere Priorität als die vorherige. Die Datei, in der der Abschnitt includes aufgeführt ist, hat eine höhere Priorität als die darin eingebundenen Dateien.

Suche

Das automatische Hinzufügen von Diensten zum DI-Container macht die Arbeit äußerst angenehm. Nette fügt Presenter automatisch zum Container hinzu, aber es können auch problemlos beliebige andere Klassen hinzugefügt werden.

Es genügt anzugeben, in welchen Verzeichnissen (und Unterverzeichnissen) nach Klassen gesucht werden soll:

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

Normalerweise möchten wir jedoch nicht alle Klassen und Schnittstellen hinzufügen, daher können wir sie filtern:

search:
	-	in: %appDir%/Forms

		# Filtern nach Dateiname (string|string[])
		files:
			- *Factory.php

		# Filtern nach Klassenname (string|string[])
		classes:
			- *Factory

Oder wir können Klassen auswählen, die mindestens eine der angegebenen Klassen erben oder implementieren:

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

Es können auch Ausschlussregeln definiert werden, d. h. Masken für Klassennamen oder erbende Vorfahren, bei deren Übereinstimmung der Dienst nicht zum DI-Container hinzugefügt wird:

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

Für alle Dienste können Tags gesetzt werden:

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

Zusammenführen

Wenn in mehreren Konfigurationsdateien Elemente mit denselben Schlüsseln erscheinen, werden sie überschrieben oder im Falle von Arrays zusammengeführt. Eine später eingebundene Datei hat eine höhere Priorität als die vorherige.

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

Bei Arrays kann das Zusammenführen durch Angabe eines Ausrufezeichens nach dem Schlüsselnamen verhindert werden:

config1.neon config2.neon Ergebnis
items:
	- 1
	- 2
items!:
	- 3
items:
	- 3
Version: 3.x