Search code examples
symfonydependency-injectioncontainerssymfony-2.6

How to correctly instantiate a service from a Command in Symfony2


I have a Command in Symfony2 that requires a ProductManager service.

I pass two arguments to this service: Doctrine's entity manager and a config array from app/config/config.yml

Here is my services.xml in the bundle:

<service id="acme.product_manager" class="Acme\ApiBundle\ProductManager" public="true">
    <argument>'@doctrine.orm.entity_manager'</argument>
    <argument>"keys"</argument>
</service>

Here is the code from the command:

protected function execute(InputInterface $input, OutputInterface $output)
{
    $productManager = $this->getProductManager();
}

public function getProductManager()
{
    $em = $this->getContainer()->get('doctrine')->getManager();
    $config = $this->getContainer()->getParameter('acme_api.config');
    $keys = $config['keys']['beta_keys'];

    $productManager = new ProductManager($em, $keys);

    return $productManager;
}

The config in app/config/config.yml:

acme_api:
    keys:
        beta_keys:
            app_key:  "XXXXXX"
            rest_api_key: "YYYYYY"

And finally the service constructor:

public function __construct(EntityManager $em, $keys)
{
}

I think the entity manager is correctly injected in the service, however I have my doubts regarding the keys argument.

Should it also be injected (like I'm doing at the moment), or it's better to somehow retrieve the config from inside the service in order to avoid passing it as an argument each time is instantiated?


Solution

  • First of all "keys" won't work.

    A good configuration would be :

    <service id="acme.product_manager" class="Acme\ApiBundle\ProductManager" public="true">
        <argument type="service" id="doctrine.orm.entity_manager" />
        <argument>%acme_api.keys%</argument>
    </service>
    

    Furthermore, when you define a service in xml/yml using DIC, it's to avoid doing it yourself in your function getProductManager.

    Your getProductionManager should be like :

    private function getProductManager()
    {
        //as defined in you services.xml
        return $this->getContainer()->get('acme.product_manager');
    }