Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I inject doctrine into Symfony2 service

I use simplified controller and have no service container. I'm trying to inject doctrine into a service. Here is the error:

ContextErrorException: Catchable Fatal Error: Argument 1 passed to Acme\Controller\WebController::__construct() must be an instance of Doctrine\ORM\EntityManager, none given, called in /home/hcs/Core/app/cache/dev/appDevDebugProjectContainer.php on line 3036 and defined in /home/hcs/Core/src/Acme/Controller/WebController.php line 28

Here is my service def:

doctrine:
  dbal:
    driver:   %database_driver%
    host:     %database_host%
    port:     %database_port%
    dbname:   %database_name%
    user:     %database_user%
    password: %database_password%
    charset:  UTF8

  orm:
    mappings:
      Acme:
        type: annotation
        dir: %kernel.root_dir%/../src/Acme/Model
        prefix: Acme\Model
        alias: Model
        is_bundle: false

services:
  WebController:
    class: Acme\Controller\WebController
    arguments: [@doctrine.orm.entity_manager ]
    parent: elnur.controller.abstract

And my class

use Doctrine\ORM\EntityManager;

/**
 * @Service("WebController", parent="elnur.controller.abstract")
 */
class WebController extends AbstractController
{ 
    protected $em;

    public function __construct(EntityManager $em)
    {
      $this->em = $em;
    }

Here is output from SF2 container (php app/console container:debug | grep -i en tity)

doctrine.orm.default_entity_manager             container EntityManager5330e85ad5afb_546a8d27f194334ee012bfe64f629947b07e4919\__CG__\Doctrine\ORM\EntityManager

doctrine.orm.entity_manager                     n/a       alias for doctrine.orm.default_entity_manager                  

doctrine.orm.validator.unique                   container Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntityValidator

form.type.entity                                container Symfony\Bridge\Doctrine\Form\Type\EntityType  

translator                                      container Symfony\Component\Translation\IdentityTranslator

I've also tried arguments: [ "@doctrine.orm.entity_manager" ] in the service definition and still nothing. I've tried cleaning my cache, but I cannot for the life of me get an EM injected. What am I doing wrong?

like image 346
Sam Levin Avatar asked Mar 27 '14 04:03

Sam Levin


1 Answers

The problem is that you're mixing both YAML service definition and DiExtra annotations for the same class. The YAML definition is full and provides the required dependency, but you haven't added @InjectParams to play with the @Service annotation. Basically, you're creating two services of the single class using different approaches and the annotations approach is not complete.

Either remove the @Service annotation from the class, or, if you prefer annotations (which I do), inject the dependencies with annotations too and get rid of the YAML service definition:

/**
 * @InjectParams({
 *    "em" = @Inject("doctrine.orm.entity_manager")
 * })
 */
public function __construct(EntityManager $em)
{
    $this->em = $em;
}

The @InjectParams annotation matches parameter names like $em to service names like @em. Since there is no @em service, you have to override the default matching with the @Inject annotation.

But there is a way to simplify it. You can alias the entity manager to @em in your YAML configuration file:

services:
    em:
        alias: doctrine.orm.entity_manager

Now you can simplify the @InjectParams annotation:

/**
 * @InjectParams
 */
public function __construct(EntityManager $em)
{
    $this->em = $em;
}
like image 189
Elnur Abdurrakhimov Avatar answered Nov 06 '22 12:11

Elnur Abdurrakhimov