Конфигурация DI-контейнера
Обзор опций конфигурации для DI-контейнера Nette.
Файл конфигурации
DI-контейнер Nette легко управляется с помощью файлов конфигурации. Они обычно записываются в формате NEON. Для редактирования рекомендуем редакторы с поддержкой этого формата.
decorator: Декоратор
di: DI-контейнер
extensions: Установка других DI-расширений
includes: Включение файлов
parameters: Параметры
search: Автоматическая регистрация сервисов
services: Сервисы
Чтобы записать строку, содержащую символ %
, необходимо
экранировать его удвоением до %%
.
Параметры
В конфигурации можно определить параметры, которые затем можно использовать как часть определений сервисов. Тем самым можно сделать конфигурацию более наглядной или объединить и выделить значения, которые будут меняться.
parameters:
dsn: 'mysql:host=127.0.0.1;dbname=test'
user: root
password: secret
На параметр dsn
можно сослаться где угодно в конфигурации
записью %dsn%
. Параметры можно использовать и внутри строк,
например '%wwwDir%/images'
.
Параметры не обязательно должны быть только строками или числами, они также могут содержать массивы:
parameters:
mailer:
host: smtp.example.com
secure: ssl
user: franta@gmail.com
languages: [cs, en, de]
На конкретный ключ можно сослаться как %mailer.user%
.
Если вам нужно в вашем коде, например, в классе, узнать значение какого-либо параметра, передайте его в этот класс. Например, в конструкторе. Не существует никакого глобального объекта, представляющего конфигурацию, у которого классы запрашивали бы значения параметров. Это было бы нарушением принципа dependency injection.
Сервисы
См. отдельную главу.
Decorator
Как массово изменить все сервисы определенного типа? Например, вызвать определенный метод у всех презентеров, которые наследуются от конкретного общего предка? Для этого существует decorator.
decorator:
# для всех сервисов, являющихся экземплярами этого класса или интерфейса
App\Presentation\BasePresenter:
setup:
- setProjectId(10) # вызовите этот метод
- $absoluteUrls = true # и установите переменную
Decorator также можно использовать для установки тегов или включения режима inject.
decorator:
InjectableInterface:
tags: [mytag: 1]
inject: true
DI
Технические настройки DI-контейнера.
di:
# показать DI-контейнер в Tracy Bar?
debugger: ... # (bool) по умолчанию true
# типы параметров, которые никогда не следует автовайрить
excluded: ... # (string[])
# разрешить ленивое создание сервисов?
lazy: ... # (bool) по умолчанию false
# класс, от которого наследуется DI-контейнер
parentClass: ... # (string) по умолчанию Nette\DI\Container
Ленивые сервисы
Настройка lazy: true
активирует ленивое (отложенное) создание
сервисов. Это означает, что сервисы не создаются в момент, когда мы
запрашиваем их из DI-контейнера, а только в момент их первого
использования. Это может ускорить запуск приложения и снизить
потребление памяти, поскольку создаются только те сервисы, которые
действительно необходимы в данном запросе.
Для конкретного сервиса ленивое создание можно изменить.
Ленивые объекты можно использовать только для пользовательских классов, а не для внутренних классов PHP. Требуется PHP 8.4 или новее.
Экспорт метаданных
Класс DI-контейнера также содержит много метаданных. Вы можете уменьшить его размер, сократив экспорт метаданных.
di:
export:
# экспортировать параметры?
parameters: false # (bool) по умолчанию true
# экспортировать теги и какие?
tags: # (string[]|bool) по умолчанию все
- event.subscriber
# экспортировать данные для autowiring и какие?
types: # (string[]|bool) по умолчанию все
- Nette\Database\Connection
- Symfony\Component\Console\Application
Если вы не используете массив $container->getParameters()
, вы можете
отключить экспорт параметров. Далее вы можете экспортировать только
те теги, по которым вы получаете сервисы методом
$container->findByTag(...)
. Если вы вообще не вызываете этот метод, вы
можете полностью отключить экспорт тегов с помощью false
.
Вы можете значительно сократить метаданные для autowiring, указав классы, которые вы
используете в качестве параметра метода $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
, имеет более
высокий приоритет, чем включенные в нем файлы.
Search
Автоматическое добавление сервисов в 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:
files: ...
classes: ...
extends: ...
implements: ...
Всем сервисам можно установить теги:
search:
- in: %appDir%
tags: ...
Слияние
Если в нескольких файлах конфигурации появляются элементы с одинаковыми ключами, они будут перезаписаны или, в случае массивов, объединены. Позже включенный файл имеет более высокий приоритет, чем предыдущий.
config1.neon | config2.neon | результат |
---|---|---|
|
|
|
Для массивов можно предотвратить слияние, указав восклицательный знак после имени ключа:
config1.neon | config2.neon | результат |
---|---|---|
|
|
|