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.

версія: 3.x