Konfiguracja kontenera DI

Przegląd opcji konfiguracyjnych dla kontenera Nette DI.

Plik konfiguracyjny

Kontener Nette DI łatwo się kontroluje za pomocą plików konfiguracyjnych. Zazwyczaj są one zapisywane w formacie NEON. Do edycji polecamy edytory z obsługą tego formatu.

 decorator: 	Dekorator
di: Kontener DI
extensions: Instalacja dodatkowych rozszerzeń DI
includes: Dołączanie plików
parameters: Parametry
search: Automatyczna rejestracja usług
services: Usługi

Aby zapisać ciąg znaków zawierający znak %, musisz go escapować podwajając na %%.

Parametry

W konfiguracji możesz zdefiniować parametry, które można następnie użyć jako część definicji usług. Dzięki temu możesz uporządkować konfigurację lub ujednolicić i wyodrębnić wartości, które będą się zmieniać.

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

Do parametru dsn odwołujemy się w dowolnym miejscu konfiguracji zapisem %dsn%. Parametry można używać również wewnątrz ciągów znaków, jak '%wwwDir%/images'.

Parametry nie muszą być tylko ciągami znaków lub liczbami, mogą również zawierać tablice:

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

Do konkretnego klucza odwołujemy się jako %mailer.user%.

Jeśli potrzebujesz w swoim kodzie, na przykład w klasie, poznać wartość dowolnego parametru, przekaż go do tej klasy. Na przykład w konstruktorze. Nie istnieje żaden globalny obiekt reprezentujący konfigurację, którego klasy pytałyby o wartości parametrów. Byłoby to naruszeniem zasady wstrzykiwania zależności.

Usługi

Zobacz osobny rozdział.

Decorator

Jak masowo modyfikować wszystkie usługi określonego typu? Na przykład wywołać określoną metodę u wszystkich prezenterów, które dziedziczą po konkretnym wspólnym przodku? Do tego służy dekorator.

decorator:
	# dla wszystkich usług, które są instancją tej klasy lub interfejsu
	App\Presentation\BasePresenter:
		setup:
			- setProjectId(10)       # wywołaj tę metodę
			- $absoluteUrls = true   # i ustaw zmienną

Dekorator można również używać do ustawiania tagów lub włączania trybu inject.

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

DI

Techniczne ustawienia kontenera DI.

di:
	# wyświetlać DIC w Tracy Bar?
	debugger: ...        # (bool) domyślnie true

	# typy parametrów, których nigdy nie autowirować
	excluded: ...        # (string[])

	# zezwolić na lazy tworzenie usług?
	lazy: ...            # (bool) domyślnie false

	# klasa, po której dziedziczy kontener DI
	parentClass: ...     # (string) domyślnie Nette\DI\Container

Usługi lazy

Ustawienie lazy: true aktywuje lazy (odroczone) tworzenie usług. Oznacza to, że usługi nie są faktycznie tworzone w momencie, gdy żądamy ich z kontenera DI, ale dopiero w chwili ich pierwszego użycia. Może to przyspieszyć start aplikacji i zmniejszyć zużycie pamięci, ponieważ tworzone są tylko te usługi, które są faktycznie potrzebne w danym żądaniu.

Dla konkretnej usługi można zmienić lazy tworzenie.

Obiekty lazy można używać tylko dla klas użytkownika, a nie dla wewnętrznych klas PHP. Wymaga PHP 8.4 lub nowszego.

Eksport metadanych

Klasa kontenera DI zawiera również wiele metadanych. Możesz ją zmniejszyć, redukując eksport metadanych.

di:
	export:
		# eksportować parametry?
		parameters: false   # (bool) domyślnie true

		# eksportować tagi i które?
		tags:               # (string[]|bool) domyślnie wszystkie
			- event.subscriber

		# eksportować dane dla autowiringu i które?
		types:              # (string[]|bool) domyślnie wszystkie
			- Nette\Database\Connection
			- Symfony\Component\Console\Application

Jeśli nie używasz tablicy $container->getParameters(), możesz wyłączyć eksport parametrów. Ponadto możesz eksportować tylko te tagi, za pomocą których uzyskujesz usługi metodą $container->findByTag(...). Jeśli metody nie wywołujesz w ogóle, możesz całkowicie wyłączyć eksport tagów za pomocą false.

Możesz znacznie zredukować metadane dla autowiringu podając klasy, których używasz jako parametr metody $container->getByType(). I ponownie, jeśli metody nie wywołujesz w ogóle (lub tylko w bootstrapie do uzyskania Nette\Application\Application), możesz eksport całkowicie wyłączyć za pomocą false.

Rozszerzenia

Rejestracja dodatkowych rozszerzeń DI. W ten sposób dodajemy np. rozszerzenie DI Dibi\Bridges\Nette\DibiExtension22 pod nazwą dibi

extensions:
	dibi: Dibi\Bridges\Nette\DibiExtension22

Następnie konfigurujemy je w sekcji dibi:

dibi:
	host: localhost

Jako rozszerzenie można dodać również klasę, która ma parametry:

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

Dołączanie plików

Kolejne pliki konfiguracyjne możemy dołączyć w sekcji includes:

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

Nazwa parameters.php nie jest literówką, konfiguracja może być zapisana również w pliku PHP, który zwróci ją jako tablicę:

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

Jeśli w plikach konfiguracyjnych pojawią się elementy o tych samych kluczach, zostaną nadpisane, lub w przypadku tablic połączone. Później dołączany plik ma wyższy priorytet niż poprzedni. Plik, w którym znajduje się sekcja includes, ma wyższy priorytet niż w nim dołączane pliki.

Automatyczne dodawanie usług do kontenera DI niezwykle ułatwia pracę. Nette automatycznie dodaje do kontenera presentery, ale można łatwo dodawać również dowolne inne klasy.

Wystarczy podać, w których katalogach (i podkatalogach) ma szukać klas:

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

Zazwyczaj jednak nie chcemy dodawać absolutnie wszystkich klas i interfejsów, dlatego możemy je filtrować:

search:
	-	in: %appDir%/Forms

		# filtrowanie według nazwy pliku (string|string[])
		files:
			- *Factory.php

		# filtrowanie według nazwy klasy (string|string[])
		classes:
			- *Factory

Lub możemy wybierać klasy, które dziedziczą lub implementują co najmniej jedną z podanych klas:

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

Można zdefiniować również reguły wykluczające, tj. maski nazwy klasy lub przodków dziedziczenia, które jeśli pasują, usługa nie zostanie dodana do kontenera DI:

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

Wszystkim usługom można ustawić tagi:

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

Łączenie

Jeśli w wielu plikach konfiguracyjnych pojawią się elementy o tych samych kluczach, zostaną nadpisane, lub w przypadku tablic połączone. Później dołączany plik ma wyższy priorytet niż poprzedni.

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

W przypadku tablic można zapobiec łączeniu, dodając wykrzyknik za nazwą klucza:

config1.neon config2.neon wynik
items:
	- 1
	- 2
items!:
	- 3
items:
	- 3
wersja: 3.x