如何在奏鸣曲管理类中获取容器实例?

Posted

技术标签:

【中文标题】如何在奏鸣曲管理类中获取容器实例?【英文标题】:How to get container instance in sonata Admin class? 【发布时间】:2012-08-26 18:45:52 【问题描述】:

我需要从我的 config.yml 中解析一些配置参数,例如启用的语言。但是当我尝试通过使用普通的 symfony 方法来做到这一点时:$this->container->get('my_params'); 它失败了,因为我的管理类扩展了 Sonata\AdminBundle\Admin\Admin 类,它没有扩展 Symfony\Component\DependencyInjection\ContainerAware 类。

请问,如何在奏鸣曲管理类中获取容器?

现在我通过重写 Sonata Admin Class 以使其扩展 ContainerAware 来解决这个问题。

【问题讨论】:

【参考方案1】:

可能已经解决,因为它是一个老问题,但仅供参考,容器已经在使用配置池的管理类中可用...

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

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

【讨论】:

管理池的 getContainer() 方法自 Sonata Admin 3.77.0 起已被弃用,并已在 4.x 中删除。请参阅其他答案以了解替代(= 正确)方法。【参考方案2】:

添加到您的管理类

/** @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-&gt;container-&gt;get()

有关更多信息,请参阅Service Container 文档

【讨论】:

这可能不适用于自定义 CRUD 控制器,因为奏鸣曲管理员想要自行分配。 一般情况下,此方法适用于任何服务。见DependencyInjection【参考方案3】:

这是在奏鸣曲管理类中使用服务的最佳方式:

只需使用 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;

看看:

Service Container documentation

【讨论】:

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

在您的特定情况下,让自定义 AdminController 类设置您的 Admin 类的参数可能是明智的。这将遵循 MVC 模式,并使您免于更改供应商捆绑包。如果您不知道如何执行此操作,请更新您的问题,我会更详细地解释。

【讨论】:

我通过在我的管理类中注入容器本身解决了这个问题,这是一个不好的部分。我使用 setter 注入而不是构造注入,因为构造应该具有完全相同的父原型。【参考方案5】:

这里是一个 liip_imagine 服务的例子:

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

【讨论】:

【参考方案6】:

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

您可以通过 Sonata Admin 类 (v4.x) 中的依赖注入来实现这一点。

例如,我已注入 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;
    
  
    ...

【讨论】:

以上是关于如何在奏鸣曲管理类中获取容器实例?的主要内容,如果未能解决你的问题,请参考以下文章

在奏鸣曲管理员中隐藏下载按钮

上传图片时如何在 symfony2 奏鸣曲媒体中设置最大上传大小

奏鸣曲管理员获取所有列表项

如何在奏鸣曲管理表单中创建子组

如何在奏鸣曲管理员中为路由设置主机?

在奏鸣曲管理员中,我们如何拥有多个级别的子管理员