Настройка DI-контейнера
Обзор вариантов конфигурации контейнера Nette DI.
Конфигурационный файл
Контейнером Nette DI легко управлять с помощью конфигурационных файлов. Обычно они записываются в формате NEON format. Мы рекомендуем использовать редактирования таких файлов редакторы с поддержкой этого формата.
decorator: Decorator
di: DI Container
extensions: Install additional DI extensions
includes: Including files
parameters: Parameters
search: Automatic service registration
services: Services
Чтобы записать строку, содержащую символ %
, вы должны
экранировать его удвоением до %%
.
Параметры
Можно задать параметры, которые затем могут быть использованы в качестве части определения сервиса. Это может помочь разделить значения, которые вы хотите изменять более регулярно:
parameters:
dsn: 'mysql:host=127.0.0.1;dbname=test'
user: root
password: secret
В любом конфигурационном файле можно ссылаться на параметр foo
через %foo%
в другом месте. Они также могут использоваться внутри
строк, таких как '%wwwDir%/images'
.
Параметры не должны быть только строками, они могут быть также значениями массива:
parameters:
mailer:
host: smtp.example.com
secure: ssl
user: franta@gmail.com
languages: [cs, en, de]
Можно ссылаться на отдельный ключ так: %mailer.user%
.
Если вам нужно получить значение любого параметра в вашем коде, например, в классе, то передайте его этому классу. Например, в конструкторе. Не существует глобального объекта конфигурации, который мог бы запрашивать значения параметров. Это противоречит принципу внедрения зависимостей.
Сервисы
См. отдельную главу.
Декоратор
Как массово редактировать все сервисы определенного типа? Нужно вызвать определенный метод для всех презентеров, наследующих от определенного общего предка? Вот откуда берется декоратор:
decorator:
# Для всех сервисов, являющихся экземплярами этого класса или интерфейса
App\UI\BasePresenter:
setup:
- setProjectId(10) # вызываем этот метод
- $absoluteUrls = true # и задаем переменную
Декоратор также можно использовать для установки тегов или включения режима внедрения.
decorator:
InjectableInterface:
tags: [mytag: 1]
inject: true
DI
Технические настройки контейнера DI:
di:
# отображать DIC в панели отладки Tracy?
debugger: ... # (bool) по умолчанию true
# типы параметров, которые не нужно монтировать автоматически
excluded: ... # (string[])
# класс, от которого наследуется контейнер DI
parentClass: ... # (string) по умолчанию Nette\DI\Container
Экспорт метаданных
Класс контейнера DI также содержит множество метаданных. Вы можете уменьшить его, сократив экспорт метаданных.
di:
export:
# экспортировать параметры
parameters: false # (bool) по умолчанию true
# экспортировать теги
tags: # (string[]|bool) по умолчанию все
- event.subscriber
# экспортировать данные для автоматического подключения
types: # (string[]|bool) по умолчанию все
- Nette\Database\Connection
- Symfony\Component\Console\Application
Если вы не используете массив $container->getParameters()
, можно
отключить экспорт параметров. Кроме того, вы можете экспортировать
только те теги, через которые вы получаете сервисы, используя метод
$container->findByTag(...)
. Если вы не вызываете этот метод вовсе, можно
полностью отключить экспорт тегов, указав значение false
.
Вы можете значительно уменьшить метаданные для автоматического
подключения, указав классы, которые вы используете в качестве
параметра в методе $container->getByType()
. И снова, если вы не вызывайте
этот метод вовсе (или только в bootstrap для
получения Nette\Application\Application
), можно полностью отключить экспорт,
указав значение false
.
Расширения
Регистрация других расширений DI. Таким образом, мы добавляем,
например, DI расширение Dibi\Bridges\Nette\DibiExtension22
под именем
dibi
:
extensions:
dibi: Dibi\Bridges\Nette\DibiExtension22
Затем мы настраиваем его в секции, которая также называется
dibi
:
dibi:
host: localhost
Вы также можете добавить класс расширения с параметрами:
extensions:
application: Nette\Bridges\ApplicationDI\ApplicationExtension(%debugMode%, %appDir%, %tempDir%/cache)
Включаемые файлы
Дополнительные файлы конфигурации могут быть вставлены в секции
includes
:
includes:
- parameters.php
- services.neon
- presenters.neon
Название parameters.php
не является опечаткой, конфигурация также
может быть записана в PHP-файле, который возвращает её в виде массива:
<?php
return [
'database' => [
'main' => [
'dsn' => 'sqlite::memory:',
],
],
];
Если в конфигурационных файлах появляются элементы с одинаковыми
ключами, они будут перезаписаны или объединены в случае
с массивами. Последующий включенный файл имеет более высокий
приоритет, чем предыдущий. Файл, в котором указана секция includes
,
имеет более высокий приоритет, чем файлы, включенные в него.
Поиск
Автоматическое добавление сервисов в контейнер DI делает работу чрезвычайно приятной. Nette автоматически добавляет презентеры в контейнер, но вы можете легко добавить любые другие классы.
Просто укажите, в каких каталогах (и подкаталогах) следует искать классы:
search:
- in: %appDir%/Forms
- in: %appDir%/Model
Обычно, однако, мы не хотим добавлять все классы и интерфейсы, поэтому мы можем отфильтровать их:
search:
- in: %appDir%/Forms
# фильтрация по имени файла (string|string[])
files:
- *Factory.php
# фильтрация по имени класса (string|string[])
classes:
- *Factory
Или мы можем выбрать классы, которые наследуют или реализуют хотя бы один из следующих классов:
search:
- in: %appDir%
extends:
- App\*Form
implements:
- App\*FormInterface
Вы также можете определить негативные правила, т. е. маски имён классов или предков, и если они соответствуют требованиям, сервис не будет добавлен в контейнер DI:
search:
- in: %appDir%
exclude:
файлы: ...
classes: ...
extends: ...
implements: ...
Для дополнительных сервисов можно определить теги:
search:
- in: %appDir%
tags: ...
Объединение
Если элементы с одинаковыми ключами появляются в нескольких конфигурационных файлах, они будут перезаписаны или объединены в случае массивов. Более поздний включенный файл имеет более высокий приоритет.
config1.neon | config2.neon | result |
---|---|---|
|
|
|
Чтобы предотвратить объединение определенного массива, используйте восклицательный знак сразу после имени массива:
config1.neon | config2.neon | result |
---|---|---|
|
|
|