23

I need to parse some configurations parameters from my config.yml such as enabled languages. But when i try to do that by using the normal symfony method: $this->container->get('my_params'); it fails because my admin class extends Sonata\AdminBundle\Admin\Admin class which does not extend the Symfony\Component\DependencyInjection\ContainerAware class.

Please, How to get the container inside the sonata Admin class ?

Now i'm resolving this problem by overriding the sonata Admin Class to make it extends the ContainerAware.

Elnur Abdurrakhimov
  • 44,533
  • 10
  • 148
  • 133
skonsoft
  • 1,786
  • 5
  • 22
  • 43

6 Answers6

53

probably already resolved, because its an old question, but just for reference, the container is already available in admin class using the configuration pool...

$this->getConfigurationPool()->getContainer();

Of course, it is better practice to inject services in the admin class, but, like in the controllers. why would someone, take the time to configure setter injection if already has the container available?

Javier Neyra
  • 1,239
  • 11
  • 12
  • 3
    The method `getContainer()` of the Admin Pool has been deprecated since Sonata Admin 3.77.0 and has been removed in 4.x. See the other answers for alternative (= the correct) methods. – 7ochem Sep 13 '21 at 13:19
17

Add in your Admin class

/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
private $container;

public function setContainer (\Symfony\Component\DependencyInjection\ContainerInterface $container) {
    $this->container = $container;
}

And add calls in services configuration(configuration can be specified in YAML, XML or PHP):

YAML

calls:
    - [ setContainer, [ @service_container ] ]

XML

 <call method="setContainer">
     <argument type="service" id="service_container" />
 </call>

Now you can using the normal symfony method: $this->container->get()

For more information see Service Container documentation

2

Here is the best way to use services in sonata admin classes:

Just inject the needed service using setter injection. Constructor injections are not allowed in this case, because you would have to override the constructor of the parent class. The constructor of the parent class accepts only 3 parameters, so you can not add another one.

The solution is:

<!-- file: services.xml -->

 <service id="skonsoft.znata.admin.keyword" class="%skonsoft.znata.admin.keyword.class%">
            <tag name="sonata.admin" manager_type="orm" group="Keyword" label="Keyword"/>
            <argument />
            <argument>%skonsoft.znata.admin.keyword.entity.class%</argument>
            <argument>SonataAdminBundle:CRUD</argument>
            <call method="setTranslationDomain">
                <argument>SkonsoftZnataBundle</argument>
            </call>

            <!-- here you inject needed services or parameters -->
            <call method="setEnabledLocales">
                <argument>%skonsoft_znata.locales%</argument>
            </call>
        </service>

Then, just add a public method in your admin class called setEnabledLocales.

/* file: MyclassAdmin.php */

 public function setEnabledLocales($locales){
    $this->enabedLocales = $locales;
}

Take a look at:

Service Container documentation

likeitlikeit
  • 5,563
  • 5
  • 42
  • 56
skonsoft
  • 1,786
  • 5
  • 22
  • 43
  • You can use constructor injection, just make sure your Admin class constructor's takes `$code`, `$class` and `$baseControllerName` as first 3 params, and then your custom dependencies. Call `parent::__construct($code, $class, $baseControllerName)`. Finally, declare your custom dependencies below the already configured `arguments` section within your services.[yml|xml|whatever]. – RockTheShow Oct 09 '15 at 14:48
1

In your particular situation, it might be wise to have a custom AdminController class set the parameters of your Admin class. This would adhere to the MVC pattern and save you from changing vendor bundles. If you don't know how to do this, please update your question and I'll explain in more detail.

likeitlikeit
  • 5,563
  • 5
  • 42
  • 56
  • I resolved this by injecting the container itself in my admin class which is a bad parctice. I used the setter injection instead of construct injection because the construct should has exactly the same prototype of parent. – skonsoft Sep 01 '12 at 15:41
0

The method getContainer() of the Admin Pool has been deprecated since Sonata Admin 3.77.0 and has been removed in v4.x.

You could achieve this with dependency injection in sonata Admin class (v4.x).

For example, I've injected ParameterBagInterface to get application params in my sonata admin.

use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;

class ProtocolAdmin extends AbstractAdmin
{
    private $params;

    public function __construct(string $code, string $class, string $baseControllerName, ParameterBagInterface $params)
    {
        parent::__construct($code, $class, $baseControllerName);
        $this->params = $params;
    }
  
    ...
}
Bhaktaraz
  • 461
  • 5
  • 13
-1

Here is an example of liip_imagine service:

 $cacheManager = $this->getConfigurationPool()->getContainer()->get('liip_imagine.cache.manager');
Shadi Akil
  • 373
  • 3
  • 11