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.