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.