问题
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