Nette DI Container

Nette DI Container je jednou z nejzajímavějších částí frameworku. Umí generovat kompilované DI kontejnery, které jsou extrémně rychlé a úžasně snadno konfigurovatelné.

Nette DI je knihovna, která poskytuje nástroje pro generování a také automatickou aktualizaci tříd kontejneru. Instruujeme ho (zpravidla) pomocí konfiguračních souborů. Kontejner, který jsme ručně vytvořili v předchozí kapitole, by se zapsal v konfiguračním formátu NEON takto:

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

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

Zápis je opravdu stručný.

Všechny závislosti deklarované v konstruktoru služeb ArticleFactory a UserController Nette DI zjistí a prováže automaticky díky tzv. autowiringu. Takže se můžete se soustředit na vývoj.

Pokud chceme závislosti předávat pomocí setteru, můžeme do definice služby přidat sekci setup.

Nette DI vygeneruje skutečně PHP kód kontejneru. Ten je proto extrémně rychlý, programátor přesně ví, co dělá, a může ho třeba i krokovat. Kontejner může mít v případě velkých aplikací desetitisíce řádků a udržovat něco takového ručně by už nejspíš ani nebylo možné.

Nette DI umí také generovat kód továren na základě rozhraní. Místo třídy ArticleFactory by tak stačílo vytvořit jen interface:

interface ArticleFactory
{
	/** @return Article */
	function create();
}

Celý příklad najdete na GitHubu.

Použití bez frameworku

Nasazení Nette DI do aplikace je velmi snadné. Nejprve jej nainstalujeme Composerem (protože stahování zipů je tááák zastaralé):

composer require nette/di

Výše uvedenou konfiguraci uložíme do souboru config.neon a pomocí třídy Nette\DI\ContainerLoader vytvoříme kontejner:

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

a pak jej necháme vytvořit objekt UserController:

$database = $container->getByType(UserController::class);
$database->query('...');

Ale ještě na chvíli zpět ke ContainerLoader. Uvedený zápis je podřízen jediné věci: rychlosti. Kontejner se vygeneruje jednou, jeho kód se zapíše do cache (adresář __DIR__ . '/temp') a při dalších požadavcích se už jen odsud načítá. Proto je načítání konfigurace umístěno do closure v metodě $loader->load().

Během vývoje je užitečné aktivovat auto-refresh mód, kdy se kontejner automaticky přegeneruje, pokud dojde ke změně jakékoliv třídy nebo konfiguračního souboru. Stačí v konstruktoru ContainerLoader uvést jako druhý argument true.

Jak vidíte, použití Nette DI rozhodně není limitované na aplikace psané v Nette, můžete jej pomocí pouhých 3 řádků kódu nasadit kdekoliv.

Použití s frameworkem Nette

Pokud vyvíjíte aplikace v Nette, konfiguraci a vytvoření kontejneru má na starosti Bootstrap.