Symfony2: Как ввести ВСЕ параметры в службу?

Как я могу ввести ВСЕ параметры в службу?

Я знаю, что могу сделать: arguments: [%some.key%] которые передадут parameters: some.key: "value" для службы __construct.

Мой вопрос заключается в том, как вводить все, что находится под parameters в сервисе?

Мне нужно это, чтобы создать службу диспетчера навигации, где различные меню / навигационные / панировочные сухари должны создаваться в соответствии с разными настройками через все записи конфигурации.

Я знаю, что я мог бы вводить столько параметров, сколько хочу, но поскольку он собирается использовать их и со временем будет расширяться, я думаю, что лучше всего передать все в самом начале.

Другим подходом могло бы быть, если бы я мог получить параметры внутри службы, как вы можете сделать в контроллере $this -> container -> getParameter('some.key'); , но я думаю, что это было бы против идеи инъекции зависимостей?

Заранее спасибо!

Примечание. Я знаю, что это решение не является BEST с точки зрения дизайна, но оно выполняет эту работу, поэтому, пожалуйста, избегайте голосования.

Вы можете вставить объект \ AppKernel, а затем получить доступ ко всем параметрам следующим образом:

config.yml:

 my_service: class: MyService\Class arguments: [@kernel] 

И внутри MyService\Class :

 public function __construct($kernel) { $this->parameter = $kernel->getContainer()->getParameter('some.key'); // or to get all: $this->parameters = $kernel->getContainer()->getParameterBag()->all(); } 

Не рекомендуется применять весь контейнер в услугу. Также, если у вас есть много параметров, которые вам нужны для вашей службы, нехорошо вставлять их все по одному в вашу службу. Вместо этого я использую этот метод:

1) В config.yml я определяю параметры, которые мне нужны для моей службы, например:

  parameters: product.shoppingServiceParams: parameter1: 'Some data' parameter2: 'some data' parameter3: 'some data' parameter4: 'some data' parameter5: 'some data' parameter6: 'some data' 

2) Затем я вставляю этот параметр корня в свою службу, например:

 services: product.shoppingService: class: Saman\ProductBundle\Service\Shopping arguments: [@translator.default, %product.shoppingServiceParams%] 

3) В службе обслуживания я могу получить доступ к этим параметрам, например:

 namespace Saman\ProductBundle\Service; use Symfony\Bundle\FrameworkBundle\Translation\Translator; class Shopping { protected $translator; protected $paramaters; public function __construct( Translator $translator, $parameters ) { $this->translator = $translator; $this->parameters = $parameters; } public function dummyFunction() { var_dump($this->getParameter('parameter2')); } private function getParameter($key, $default = null) { if (isset($this->parameters[$key])) { return $this->parameters[$key]; } return $default; } } 

4) Я могу также установить разные значения для разных сред. Например, в config_dev.yml

  parameters: product.shoppingServiceParams: parameter1: 'Some data for dev' parameter2: 'some data for dev' parameter3: 'some data for dev' parameter4: 'some data for dev' parameter5: 'some data for dev' parameter6: 'some data' 

Я считаю, что вы должны передавать параметры по отдельности. Я думаю, что это сделано таким образом, чтобы ваш класс обслуживания не зависел от AppKernel. Таким образом, вы можете повторно использовать свой класс обслуживания вне вашего проекта Symfony. Что-то, что полезно при тестировании вашего класса обслуживания.

AppKernel будет работать, но это еще хуже (с точки зрения перспективы), чем инъекция контейнера, поскольку в нем есть еще больше вещей.

Вы можете посмотреть xxxProjectContainer в вашем каталоге кеша. Оказывается, что отсортированные параметры скомпилированы непосредственно в него как большой массив. Таким образом, вы можете ввести контейнер, а затем просто вытащить параметры. Нарушает букву закона, но не дух закона.

 class MyService { public function __construct($container) { $this->parameters = $container->parameters; // Then discard container to preclude temptation 

И только что-то вроде беспорядка, и я обнаружил, что могу это сделать:

  $container = new \arbiterDevDebugProjectContainer(); echo 'Parameter Count ' . count($container->parameters) . "\n"; 

Таким образом, вы можете создать сервис, в котором в основном была пустая копия главного контейнера, и вводить его только для получения параметров. Примите во внимание флагов dev / debug, которые могут быть больны.

Я подозреваю, что вы также можете сделать это с помощью компилятора, но никогда не пробовали.

Другой вариант, как легко получить параметры – вы можете просто установить ParameterBag в свою службу. Вы можете сделать это по-разному – через аргументы или с помощью методов набора. Позвольте мне показать мой пример с помощью метода set.

Поэтому в services.yml вы должны добавить что-то вроде:

 my_service: class: MyService\Class calls: - [setParameterBag, ["@=service('kernel').getContainer().getParameterBag()"]] 

и в классе MyService \ Class просто добавьте использование:

 use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface; 

и создать 2 метода:

 /** * Set ParameterBag for repository * * @param ParameterBagInterface $params */ public function setParameterBag(ParameterBagInterface $params) { $this->parameterBag = $params; } /** * Get parameter from ParameterBag * * @param string $name * @return mixed */ public function getParameter($name) { return $this->parameterBag->get($name); } 

и теперь вы можете использовать в классе:

 $this->getParameter('your_parameter_name'); 

Предложение определить службу в services.yml, которая будет вводить параметрBag и разрешать доступ к любому из ваших параметров

 service.container_parameters: public: false class: stdClass factory_service: service_container factory_method: getParameterBag 

Внесите свой сервис, и вы можете получить свой параметр, используя ниже

 $parameterService->get('some.key'); 

Поскольку альтернативный подход состоял бы в том, что вы действительно можете вводить параметры приложения в свою службу через Container-> getParameterBag, вы добавляете расширение DI

  <?php namespace Vendor\ProjectBundle\DependencyInjection; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Config\FileLocator; use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\DependencyInjection\Loader; /** * This is the class that loads and manages your bundle configuration * * To learn more see {@link http://symfony.com/doc/current/cookbook/bundles/extension.html} */ class VendorProjectExtension extends Extension { /** * {@inheritDoc} */ public function load(array $configs, ContainerBuilder $container) { $configuration = new Configuration(); $config = $this->processConfiguration($configuration, $configs); $loader = new Loader\YamlFileLoader($container, new FileLocator(__DIR__ . '/../Resources/config')); $loader->load('services.yml'); /** set params for services */ $container->getDefinition('my.managed.service.one') ->addMethodCall('setContainerParams', array($container->getParameterBag()->all())); $container->getDefinition('my.managed.service.etc') ->addMethodCall('setContainerParams', array($container->getParameterBag()->all())); } } 

Обратите внимание, что мы не можем напрямую вводить объект ParameterBag, потому что он бросает:

[Symfony \ Component \ внедрение зависимости \ Exception \ RuntimeException]
Невозможно сбросить контейнер службы, если параметр является объектом или ресурсом.

Протестировано по версии 2.3.4 Symfony