Right way to inject container service in Sonata Admin Bundle

一个人想着一个人 提交于 2019-12-11 12:41:42

问题


I'm trying to inject the service container in my Sonata Admin class in order to use it at configureFormFields method. This is what I have:

config.yml (sonata services definition)

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'));
    }

}

But I'm getting this error:

ContextErrorException: Catchable Fatal Error: Object of class appDevDebugProjectContainer could not be converted to string in /var/www/html/tan/var/cache/dev/classes.php line 12979

What's wrong there?


回答1:


Since your constructor takes 4 arguments where the 4th is the service container, you need to pass in the service container 4th:

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:


If you only want to access container in admin class you can simply call

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

which will simple return the container for a formal way create a base admin class for your bundle which will extend admin class of sonata and then you can define your function in base admin class to return a container and use it in your child admin classes, product base admin class will look like

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();
    }
}

And now in your child class you can acess container through $this->getContainer() which will call getContainer() function of your ProductBaseAdmin class

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'));
    }
}



回答3:


Trying to add 4th argument to Admin constructor lead me to error:

"Argument 4 passed to AppBundle\Admin\WebLabAbstractMessageAdmin::__construct() must be an instance of Doctrine\ORM\EntityManager, none given" no matter what service I tried to pass to arguments.

So I used calls approach:

#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']]

with setters in the admin class

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

My versions are: "symfony/symfony": "3.2.*", "sonata-project/admin-bundle": "^3.10".

Hope it helps someone.



来源:https://stackoverflow.com/questions/25149446/right-way-to-inject-container-service-in-sonata-admin-bundle

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!