4
votes

I have created a service at ./src/Service, and I want to use the Doctrine Entity Manager in my service, so I inject it in the __construct method:

namespace App\Service;

use App\Entity\Category;
use Doctrine\ORM\EntityManagerInterface;
use Twig\Environment;
use Twig\Error\LoaderError;
use Twig\Error\RuntimeError;
use Twig\Error\SyntaxError;

class CommonPageGenerator
{
  /**
   * @var EntityManagerInterface
   */
  private $em;
  /**
   * @var Environment
   */
  private $templating;

  public function __construct(EntityManagerInterface $em, Environment $templating)
  {
    $this->em = $em;
    $this->templating = $templating;
  }

  public function page1($title){ return; }

}

I then inject this service in a controller:

  /**
   * @Route("/overseas", name="overseas")
   * @param CommonPageGenerator $commonPageGenerator
   */
  public function overseas(CommonPageGenerator $commonPageGenerator)
  {
    return $commonPageGenerator->page1('overseas');
  }

But I get the following error:

Argument 1 passed to App\Service\CommonPageGenerator::__construct() must implement interface Doctrine\ORM\EntityManagerInterface, string given, called in /Users/tangmonk/Documents/mygit/putixin.com/putixin_backend/var/cache/dev/ContainerB7I3rzx/getCommonPageGeneratorService.php on line 11

enter image description here

My services.yaml file:

parameters:

services:
    # default configuration for services in *this* file
    _defaults:
        autowire: true      # Automatically injects dependencies in your services.
        autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
        bind:
          $em: 'doctrine.orm.default_entity_manager'

I am using Symfony 4.3

1
Basically you've to inject your dependency in your services.yaml file unless you are on Sf4.3+ (not sure if it does exists since then) and you're using autowiring Check [this post ](stackoverflow.com/questions/10427282/…) it has a bunch of useful information that could help youReynierPM

1 Answers

4
votes

You do not need binding $em to the Doctrine entity manager.

If you remove that line and leave the type hint only (__construct(EntityManagerInterface $em, Environment $templating) should be enough.

Thus leaving your __construct() method like this:

// you can of course import the EngineInterface with a "use" statement. 
public function __construct(
                    EntityManagerInterface $em,
                    Environment $templating)
  {
    $this->em = $em;
    $this->templating = $templating;
  }

If you do this and remove the bind configuration, automatic dependency injection should work by itself.

(Normally I would suggest replacing Environment with Symfony\Bundle\FrameworkBundle\Templating\EngineInterface, to depend in the interface provided by the framework to integrate with the templating component. But this component and its integration have been deprecated in 4.3, and will be removed by 5.0; so you are fine by depending directly on Twig.)

But if want to you leave the binding in place for some reason, you should prefix the service name with an @ symbol, so Symfony knows you are trying to inject a service and not string. Like so:

 bind:
          $em: '@doctrine.orm.default_entity_manager'

Docs.