Nette DI Container
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
:
$controller = $container->getByType(UserController::class);
$controller->someMethod();
Під час розробки корисно активувати режим автоматичного оновлення,
коли контейнер автоматично перегенерується, якщо зміниться будь-який
клас або конфігураційний файл. Достатньо в конструкторі
ContainerLoader
вказати true
як другий аргумент.
$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);
Використання з фреймворком Nette
Як ми показали, використання Nette DI не обмежується застосунками, написаними на Nette Framework, ви можете впровадити його де завгодно за допомогою лише 3 рядків коду. Однак, якщо ви розробляєте застосунки на Nette Framework, конфігурацією та створенням контейнера займається Bootstrap.