Symfony2: How to inject ALL parameters in a service?

后端 未结 7 849
既然无缘
既然无缘 2020-12-28 14:14

How can I inject ALL parameters in a service?

I know I can do: arguments: [%some.key%] which will pass the parameters: some.key: \"value\"

相关标签:
7条回答
  • 2020-12-28 14:47

    Note: I know that this solution is not BEST from design point of view, but it does the job, so please avoid down-voting.

    You can inject \AppKernel object and then access all parameters like this:

    config.yml:

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

    And inside MyService\Class:

    public function __construct($kernel)
    {
        $this->parameter = $kernel->getContainer()->getParameter('some.key');
        // or to get all:
        $this->parameters = $kernel->getContainer()->getParameterBag()->all();
    }
    
    0 讨论(0)
  • 2020-12-28 14:48

    It is not a good practice to inject the entire Container into a service. Also if you have many parameters that you need for your service it is not nice to inject all of them one by one to your service. Instead I use this method:

    1) In config.yml I define the parameters that I need for my service like this:

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

    2) Then I inject this root parameter to my service like:

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

    3) In may service I can access these parameters like:

    namespace Saman\ProductBundle\Service;
    
    use Symfony\Bundle\FrameworkBundle\Translation\Translator;
    
    class Shopping
    {   
        protected $translator;
        protected $parameters;
    
        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) I can also set different values for different environments. For example in 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'
    
    0 讨论(0)
  • 2020-12-28 14:57

    As alternative approach would be that you can actually inject application parameters into your service via Container->getParameterBag in you bundle DI Extension

        <?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()));
    
            }
    }
    

    Please note that we can not inject ParameterBag object directly, cause it throws:

    [Symfony\Component\DependencyInjection\Exception\RuntimeException]
    Unable to dump a service container if a parameter is an object or a resource.

    Tested under Symfony version 2.3.4

    0 讨论(0)
  • 2020-12-28 15:01

    Another variant how to get parameters easy - you can just set ParameterBag to your service. You can do it in different ways - via arguments or via set methods. Let me show my example with set method.

    So in services.yml you should add something like:

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

    and in class MyService\Class just add use:

    use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
    

    and create 2 methods:

    /**                                                                                                                                                                      
     * 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);
    }
    

    and now you can use in class:

    $this->getParameter('your_parameter_name');
    
    0 讨论(0)
  • 2020-12-28 15:01

    I believe you're supposed to pass the parameters individually. I think it's made that way by design so your service class is not dependent on the AppKernel. That way you can reuse your service class outside your Symfony project. Something that is useful when testing your service class.

    0 讨论(0)
  • 2020-12-28 15:06

    Suggestion to define a service at services.yml, which will inject the parameterBag and allow access to any of your parameter

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

    Inject your service, and u can get your parameter using below

    $parameterService->get('some.key');
    
    0 讨论(0)
提交回复
热议问题