【问题标题】:Right way to inject container service in Sonata Admin Bundle在 Sonata Admin Bundle 中注入容器服务的正确方法
【发布时间】:2014-09-28 17:49:42
【问题描述】:

我正在尝试在我的 Sonata Admin 类中注入 service container,以便在 configureFormFields 方法中使用它。这就是我所拥有的:

config.yml(奏鸣曲服务定义)

services:
  tan.product.admin.product:
    class: Tan\ProductBundle\Admin\ProductAdmin
    tags:
      - { name: sonata.admin, manager_type: orm, group: Product, label: Product }
    arguments: [ null, Tan\ProductBundle\Entity\Product, @service_container]

ProductAdmin.php

class ProductAdmin extends Admin
{

    /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
    private $container;
    public $supportsPreviewMode = true;

    /**
     * @param string $code
     * @param string $class
     * @param string $baseControllerName
     */
    public function __construct($code, $class, $baseControllerName, $container = null)
    {
        parent::__construct($code, $class, $baseControllerName);
        $this->container = $container;
    }

    // other methods 

    protected function configureFormFields(FormMapper $form)
    {

        $helper = $this->container->get('oneup_uploader.templating.uploader_helper');
        $endpoint = $helper->endpoint('products');

        $form
                ->add('product_name', null, array('label' => 'Nombre'))
                ->add('product_description', null, array('label' => 'Descripción'));
    }

}

但是我收到了这个错误:

ContextErrorException:可捕获的致命错误:类的对象 appDevDebugProjectContainer 无法转换为字符串 /var/www/html/tan/var/cache/dev/classes.php 第 12979 行

怎么了?

【问题讨论】:

  • 为什么你不能将 'SonataAdminBundle:CRUD' 作为参数传递?
  • @Gara 我从不知道为什么它传递该参数的地方复制了它,以前从未见过它,反正我只是删除了参数并且问题仍然存在所以这不是问题

标签: php symfony dependency-injection sonata-admin php-5.5


【解决方案1】:

由于您的构造函数采用 4 个参数,其中第 4 个是服务容器,因此您需要传入第 4 个服务容器:

services:
  tan.product.admin.product:
  class: Tan\ProductBundle\Admin\ProductAdmin
  tags:
      - { name: sonata.admin, manager_type: orm, group: Product, label: Product }
  arguments: [ null, Tan\ProductBundle\Entity\Product, null, @service_container]

【讨论】:

    【解决方案2】:

    尝试向 Admin 构造函数添加第 4 个参数导致我出错:

    “传递给 AppBundle\Admin\WebLabAbstractMessageAdmin::__construct() 的参数 4 必须是 Doctrine\ORM\EntityManager 的一个实例,没有给定”无论我尝试将什么服务传递给参数。

    所以我使用了调用方法:

    #services.yml
    app.admin.twitter_message:
        class: AppBundle\Admin\WebLabAbstractMessageAdmin
        arguments: [~, AppBundle\Entity\Twitter\Message, SonataAdminBundle:CRUD]
        tags:
            - { name: sonata.admin, manager_type: orm, group: operator, label: Message, show_in_dashboard: false }
        calls:
            - ["setEntityManager", ['@doctrine.orm.entity_manager']]
            - ["setParentRepository", ['@app.doctrine.repository.twitter.conversation']]
    

    在管理类中使用设置器

    #MessageAdmin.php
    /**
     * @var EntityManager
     */
    private $entityManager;
    
    private $parentRepository;
    
    /**
     * @param EntityManager $entityManager
     * @return self
     */
    public function setEntityManager(EntityManager $entityManager): self
    {
        $this->entityManager = $entityManager;
        return $this;
    }
    
    /**
     * @param $parentRepository
     * @return self
     */
    public function setParentRepository($parentRepository): self
    {
        $this->parentRepository = $parentRepository;
        return $this;
    }
    

    我的版本是:“symfony/symfony”:“3.2.*”、“sonata-project/admin-bundle”:“^3.10”。

    希望它对某人有所帮助。

    【讨论】:

      【解决方案3】:

      如果你只想访问管理类中的容器,你可以简单地调用

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

      这将简单地以正式方式返回容器为您的捆绑包创建一个基本管理类,它将扩展奏鸣曲的管理类,然后您可以在基本管理类中定义您的函数以返回一个容器并在您的子管理中使用它类,产品基础管理类看起来像

      use Sonata\AdminBundle\Admin\Admin;
      
      class ProductBaseAdmin extends Admin
      {
          public function __construct($code, $class, $baseControllerName)
          {
                  parent::__construct($code, $class, $baseControllerName);
          }
          public function getContainer(){
              return $this->getConfigurationPool()->getContainer();
          }
      }
      

      现在在您的子类中,您可以通过 $this->getContainer() 访问容器,这将调用您的 ProductBaseAdmin 类的 getContainer() 函数

      use Tan\ProductBundle\Admin\ProductBaseAdmin
      class ProductAdmin extends ProductBaseAdmin
      {
          protected function configureFormFields(FormMapper $form)
          {
      
              $helper = $this->getContainer()->get('oneup_uploader.templating.uploader_helper');
              $endpoint = $helper->endpoint('products');
      
              $form
                      ->add('product_name', null, array('label' => 'Nombre'))
                      ->add('product_description', null, array('label' => 'Descripción'));
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-03
        • 2013-03-06
        • 2017-08-05
        • 2016-04-20
        • 2017-10-03
        • 2014-01-29
        • 2016-10-11
        相关资源
        最近更新 更多