Nette DI контейнер
Nette DI е една от най-интересните библиотеки на Nette. Тя може да генерира и автоматично да актуализира компилирани DI контейнери, които са изключително бързи и невероятно лесни за конфигуриране.
Формата на сървисите, които DI контейнерът трябва да създава, обикновено дефинираме с помощта на конфигурационни файлове във формат NEON. Контейнерът, който ръчно създадохме в предишната глава, би се записал така:
parameters:
db:
dsn: 'mysql:'
user: root
password: '***'
services:
- Nette\Database\Connection(%db.dsn%, %db.user%, %db.password%)
- ArticleFactory
- UserController
Записът е наистина кратък.
Всички зависимости, декларирани в конструкторите на класовете
ArticleFactory
и UserController
, Nette DI само открива и предава
благодарение на т.нар. autowiring,
затова в конфигурационния файл не е необходимо да се посочва нищо. Така
че дори ако параметрите се променят, не е необходимо да променяте нищо
в конфигурацията. Nette контейнерът автоматично ще се прегенерира. Вие
можете да се съсредоточите изцяло върху разработката на
приложението.
Ако искаме да предаваме зависимости чрез сетъри, използваме за това секцията setup.
Nette DI генерира директно PHP код на контейнера. Резултатът е файл
.php
, който можете да отворите и изучавате. Благодарение на това
виждате точно как работи контейнерът. Можете също да го дебъгвате в IDE и
да го проследявате стъпка по стъпка. И най-важното: генерираният PHP е
изключително бърз.
Nette DI може също да генерира код на фабрики въз основа на предоставен
интерфейс. Затова вместо клас ArticleFactory
ще ни е достатъчно да
създадем в приложението само интерфейс:
interface ArticleFactory
{
function create(): Article;
}
Целият пример можете да намерите в GitHub.
Самостоятелна употреба
Внедряването на библиотеката Nette DI в приложение е много лесно. Първо я инсталираме с Composer (защото изтеглянето на zip файлове е тааака остаряло):
composer require nette/di
Следващият код създава инстанция на DI контейнер според
конфигурацията, съхранена във файла config.neon
:
$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp');
$class = $loader->load(function ($compiler) {
$compiler->loadConfig(__DIR__ . '/config.neon');
});
$container = new $class;
Контейнерът се генерира само веднъж, неговият код се записва в кеша
(директория __DIR__ . '/temp'
) и при следващи заявки се зарежда
само оттам.
За създаване и получаване на сървиси служат методите getService()
или getByType()
. Така създаваме обект UserController
:
$database = $container->getByType(UserController::class);
$database->query('...');
По време на разработка е полезно да се активира режимът на
автоматично опресняване, при който контейнерът автоматично се
прегенерира, ако настъпи промяна в някой клас или конфигурационен
файл. Достатъчно е в конструктора на ContainerLoader
да се посочи като
втори аргумент true
.
$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);
Използване с Nette Framework
Както показахме, използването на Nette DI не е ограничено до приложения, написани в Nette Framework, можете да го внедрите навсякъде само с 3 реда код. Ако обаче разработвате приложения в Nette Framework, конфигурацията и създаването на контейнера се управляват от Bootstrap.