Symfony Dependency Injection внедряет новый экземпляр класса
Я использую Symfony / компонент зависимости-инъекции (примечание: не используется полная структура стека)
При регистрации нового сервиса я хочу добавить в конструктор новый экземпляр класса. Пример:
$container->register('session', 'Vendor\Core\Session')
->addArgument(new PhpBridgeSessionStorage());
Пример работает очень хорошо, но что если я захочу использовать файлы yml для определения этого сервиса? Что-то вроде:
services:
session:
class: Vendor\Core\Session
arguments: [ new Class\To\Inject ]
Я вынужден определить Class\To\Inject как новый сервис? или создать сервисную фабрику?
3 ответа
Области применения устарели с 2.8. использование shared: false
вместо.
http://symfony.com/doc/current/cookbook/service_container/shared.html
services:
session:
class: Vendor\Core\Session
arguments: [ "@inject.me" ]
inject.me:
class: Class\To\Inject
shared: false
Теперь я знаю, что этот вопрос довольно старый, но здесь есть хитрость, которую можно использовать, чтобы избежать определения каждого простого класса как службы, определяющей службу "фабричного класса", которая получает класс для создания в качестве аргумента, а затем через "язык выражения" вводит в качестве аргумента:
<?php
final class ClassFactory
{
public static function create($class, array $arguments = [])
{
return new $class($arguments);
}
}
создать новый сервис
app.class_factory: class: ClassFactory
после внедрения новых классов вот так:
аргументы: ['@=service("app.class_factory").create("Monolog\Logger")']
Для Symfony >=2.8 вы также можете воспользоваться функцией "автоподключение" -> http://symfony.com/blog/new-in-symfony-2-8-service-auto-wiring
Да, все вводимые вами классы должны быть услугами. Вы можете дать им объем prototype
создавать новый экземпляр каждый раз, когда он запрашивается.
Для получения дополнительной информации см.: http://symfony.com/doc/current/cookbook/service_container/scopes.html
Я сам искал этот ответ для библиотеки, которой просто нужно создать некоторые объекты-значения (службы) для других служб, и мне казалось, что все эти службы в YAML (с длинными уникальными именами) загрязняют конфигурацию службы по сравнению с определением объекты значения без имени службы в PHP.
В обычных приложениях это на самом деле не проблема при использовании текущей версии Symfony (3.4+), где все службы по умолчанию являются частными, поскольку контейнер служб заметит себя, если частная служба используется только один раз, а затем встроит ее (так что имя не будет использоваться), в результате получится точно такой же код контейнера службы, как при определении службы без имени в PHP.
Итак, пока вы объявляете все службы закрытыми (или используете значения по умолчанию в Symfony 3.4+), они будут соответствующим образом оптимизированы (и удалены, если не используются).