Kontener Nette DI

Nette DI jest jedną z najciekawszych bibliotek Nette. Potrafi generować i automatycznie aktualizować skompilowane kontenery DI, które są ekstremalnie szybkie i niezwykle łatwe w konfiguracji.

Postać usług, które ma tworzyć kontener DI, definiujemy zazwyczaj za pomocą plików konfiguracyjnych w formacie NEON. Kontener, który ręcznie utworzyliśmy w poprzednim rozdziale, zapisałby się tak:

parameters:
	db:
		dsn: 'mysql:'
		user: root
		password: '***'

services:
	- Nette\Database\Connection(%db.dsn%, %db.user%, %db.password%)
	- ArticleFactory
	- UserController

Zapis jest naprawdę zwięzły.

Wszystkie zależności zadeklarowane w konstruktorach klas ArticleFactory i UserController Nette DI samo wykryje i przekaże dzięki tzw. autowiringu, dlatego w pliku konfiguracyjnym nie trzeba niczego podawać. Więc nawet jeśli dojdzie do zmiany parametrów, nie musisz niczego zmieniać w konfiguracji. Kontener Nette automatycznie się przgeneruje. Ty możesz skupić się wyłącznie na rozwoju aplikacji.

Jeśli chcemy przekazywać zależności za pomocą setterów, użyjemy do tego sekcji setup.

Nette DI generuje bezpośrednio kod PHP kontenera. Wynikiem jest więc plik .php, który możesz otworzyć i studiować. Dzięki temu dokładnie widzisz, jak działa kontener. Możesz go również debugować w IDE i krokowo śledzić. A co najważniejsze: wygenerowany PHP jest ekstremalnie szybki.

Nette DI potrafi również generować kod fabryk na podstawie dostarczonego interfejsu. Dlatego zamiast klasy ArticleFactory wystarczy nam stworzyć w aplikacji tylko interfejs:

interface ArticleFactory
{
	function create(): Article;
}

Cały przykład znajdziesz na GitHubie.

Samodzielne użycie

Wdrożenie biblioteki Nette DI do aplikacji jest bardzo łatwe. Najpierw zainstalujemy ją Composerem (ponieważ pobieranie zipów jest taaak przestarzałe):

composer require nette/di

Poniższy kod tworzy instancję kontenera DI zgodnie z konfiguracją zapisaną w pliku config.neon:

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
$class = $loader->load(function ($compiler) {
	$compiler->loadConfig(__DIR__ . '/config.neon');
});
$container = new $class;

Kontener generuje się tylko raz, jego kod zapisuje się do cache (katalog __DIR__ . '/temp') i przy kolejnych żądaniach jest już tylko stamtąd odczytywany.

Do tworzenia i pobierania usług służą metody getService() lub getByType(). W ten sposób utworzymy obiekt UserController:

$controller = $container->getByType(UserController::class);
$controller->someMethod();

Podczas rozwoju przydatne jest aktywowanie trybu auto-refresh, w którym kontener automatycznie się przgeneruje, jeśli dojdzie do zmiany jakiejkolwiek klasy lub pliku konfiguracyjnego. Wystarczy w konstruktorze ContainerLoader podać jako drugi argument true.

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);

Użycie z frameworkiem Nette

Jak pokazaliśmy, użycie Nette DI nie jest ograniczone do aplikacji pisanych w Nette Framework, możesz go za pomocą zaledwie 3 linii kodu wdrożyć gdziekolwiek. Jeśli jednak rozwijasz aplikacje w Nette Framework, konfigurację i tworzenie kontenera ma na starcie Bootstrap.

wersja: 3.x