Nette DI-контейнер

Nette DI Container – одна з найцікавіших частин фреймворку. Він може генерувати скомпільовані DI-контейнери, які надзвичайно швидкі та напрочуд прості в налаштуванні.

Nette 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 завдяки так званому автозв'язуванню. Таким чином, ви можете зосередитися на розробці. Тож навіть якщо параметри зміняться, вам не потрібно нічого змінювати в конфігурації. Nette автоматично регенерує контейнер. Ви можете зосередитися виключно на розробці програми.

Якщо ви хочете передавати залежності за допомогою сетера, ми можемо додати секцію setup у визначення сервісу.

Nette DI буде фактично генерувати PHP-код для контейнера. Тому він надзвичайно швидкий, програміст точно знає, що він робить, і навіть може переступати через нього. Для великих додатків контейнер може складатися з десятків тисяч рядків, і підтримувати щось подібне вручну, імовірно, вже неможливо.

Nette DI також може генерувати код фабрики на основі інтерфейсу. Таким чином, замість класу ArticleFactory вам потрібно буде просто створити інтерфейс:

interface ArticleFactory
{
	function create(): Article;
}

Ви можете знайти повний приклад на GitHub.

Використання без фреймворка

Використовувати Nette DI в додатку дуже просто. Спочатку ми встановимо його за допомогою Composer (тому що завантаження zip-файлів вже застаріло):

composer require nette/di

Ми збережемо наведену вище конфігурацію у файлі config.neon і створимо контейнер, використовуючи клас Nette\DI\ContainerLoader:

$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('...');

Під час розроблення корисно ввімкнути режим автооновлення, за якого контейнер автоматично оновлюється при зміні будь-якого класу або файлу конфігурації. Просто вкажіть true як другий аргумент у конструкторі ContainerLoader.

$loader = new Nette\DI\ContainerLoader(__DIR__ . '/temp', true);

Використання з Nette Framework

Як ми показали, використання Nette DI не обмежується додатками, написаними на Nette Framework, ви можете розгорнути його де завгодно, використовуючи всього 3 рядки коду. Якщо ви розробляєте додатки в Nette, конфігурування і створення контейнера здійснюється за допомогою класу Bootstrap.

версію: 3.x