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
{
function create(): Article;
}
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.