如何在Sonata Admin类中获取容器实例?

23
我需要从我的config.yml文件中解析一些配置参数,例如启用的语言设置。但是当我尝试使用Symfony的常规方法来实现: $this->container->get('my_params'); 时失败了,因为我的admin类继承自Sonata\AdminBundle\Admin\Admin 而不是继承自Symfony\Component\DependencyInjection\ContainerAware类。
请问如何在Sonata Admin类中获取容器?
现在我通过重写Sonata Admin Class来使其继承ContainerAware类来解决这个问题。
6个回答

53

可能已经解决,因为这是一个旧问题,但只是作为参考,容器已经在管理类中使用配置池可用...

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

当然,在管理类中注入服务是更好的实践,但就像在控制器中一样。如果已经有容器可用,为什么还要花时间配置setter注入呢?


3
自从 Sonata Admin 3.77.0 版本起,Admin Pool 的方法 getContainer() 已被弃用,并已在 4.x 版本中删除。请参考其他答案,了解可替代(即正确)的方法。 - 7ochem

18
在您的Admin类中添加。
/** @var \Symfony\Component\DependencyInjection\ContainerInterface */
private $container;

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

并在服务配置中添加调用(配置可以用YAML、XML或PHP指定):

YAML

calls:
    - [ setContainer, [ @service_container ] ]

XML

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

现在您可以使用常规的Symfony方法:$this->container->get()

了解更多信息,请参阅Service Container文档。


由于Sonata Admin想要分配自己,所以这可能在自定义CRUD控制器中无法正常工作。 - Thomas Kekeisen
通常情况下,这种方法应该适用于任何服务。请参阅DependencyInjection - Максим Шатов

2

以下是在Sonata Admin类中使用服务的最佳方法:

只需使用setter注入注入所需服务。在这种情况下不允许使用构造函数注入,因为您必须重写父类的构造函数。父类的构造函数仅接受3个参数,因此无法添加另一个参数。

解决方案如下:

<!-- 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>

然后,在您的管理类中添加一个名为setEnabledLocales的公共方法即可。
/* file: MyclassAdmin.php */

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

请看:

请查看:

服务容器文档


您可以使用构造函数注入,只需确保您的Admin类构造函数将$code$class$baseControllerName作为前3个参数,然后是您的自定义依赖项。调用parent::__construct($code, $class, $baseControllerName)。最后,在服务[yml|xml|whatever]的已配置“arguments”部分下方声明您的自定义依赖项即可。 - RockTheShow

1
在您的特定情况下,最好创建一个自定义的AdminController类来设置您的Admin类的参数。这将遵循MVC模式,并避免更改供应商捆绑包。如果您不知道如何做到这一点,请更新您的问题,我会详细解释。

我通过将容器本身注入到我的管理类中来解决了这个问题,但这是一种不好的做法。我使用了setter注入而不是构造函数注入,因为构造函数应该具有与父类完全相同的原型。 - skonsoft

0

自从 Sonata Admin 3.77.0 版本,Admin Pool 的 getContainer() 方法已被弃用,并在 v4.x 版本中被移除。

在 sonata Admin class (v4.x) 中可以使用依赖注入来实现此功能。

例如,我在我的 sonata admin 中注入了 ParameterBagInterface 来获取应用程序参数。

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;
    }
  
    ...
}

-1

这是一个关于liip_imagine服务的示例:

 $cacheManager = $this->getConfigurationPool()->getContainer()->get('liip_imagine.cache.manager');

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接