55

How do I use Doctrine in a service container?

The Code just causes an error message "Fatal error: Call to undefined method ...::get()".

<?php

namespace ...\Service;

use Doctrine\ORM\EntityManager;
use ...\Entity\Header;

class dsdsf
{ 
    protected $em;

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

    public function create()
    {
        $id = 10;
        $em = $this->get('doctrine')->getEntityManager();
        $em->getRepository('...')->find($id);
    }
}

services.yml

service:
    site:
        class: ...\Service\Site
user1075510
  • 561
  • 1
  • 4
  • 5

8 Answers8

85

According to your code, you already have an EntityManager injected. You don't need to call $em = $this->get('doctrine')->getEntityManager() — just use $this->em.

If you don't inject an EntityManager already, read this.

UPDATE:

You need to make the container inject an EntityManager into your service. Here's an example of doing it in config.yml:

services:
    your.service:
        class: YourVendor\YourBundle\Service\YourService
        arguments: [ @doctrine.orm.entity_manager ]

I prefer to define bundles' services in their own services.yml files, but that's a bit more advanced, so using config.yml is good enough to get started.

Elnur Abdurrakhimov
  • 44,533
  • 10
  • 148
  • 133
  • 1
    Do you mean like this? $this->em->getRepository('...')->find($id); "atchable Fatal Error: Argument 1 passed to ...::__construct() must be an instance of Doctrine\ORM\EntityManager, none given" – user1075510 Dec 01 '11 at 14:56
  • 1
    Yes, I meant that. You're getting this error because you're not injecting an EntityManager from the container. I'll update my answer. – Elnur Abdurrakhimov Dec 01 '11 at 15:50
  • @user1075510: If this is the best answer, please checkmark it. – webbiedave Mar 23 '12 at 15:05
  • Can we also pass in `arguments: [@doctrine]` and just call `$this->doctrine->getEntityManager()` ? I seem to be getting a "A new entity was found through the relationship" error whenever I pass in doctrine.orm.entity_manager, but it gets resolved whenever I use the latter – Reza S Dec 28 '12 at 20:33
  • 2
    It's also better to pass Doctrine and call getEntityManager every single time because the entity manager gets closed after Database Level Errors. So if you want to manually do stuff after a known transaction failure, your screwed. – Ashley Simons Feb 11 '13 at 00:50
  • or [ @doctrine.orm.default_entity_manager ] its the same thing :) – DevWL Aug 13 '16 at 20:40
10

For easily accessing the Entitymanager use the following one:

//services.yml
  your service here:
    class: yourclasshere
    arguments: [@doctrine.orm.entity_manager]

And in the class itself:

class foo
{
  protected $em;



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

  public function bar()
  {
      //Do the Database stuff
      $query = $this->em->createQueryBuilder();

      //Your Query goes here

      $result = $query->getResult();
  }
}

This is my first answer so any comments are appreciated :)

Community
  • 1
  • 1
MaXxer90
  • 167
  • 1
  • 5
3

Please try this code:

 $em=$this->container->get('doctrine')->getEntityManager();

 $rolescheduels=$em->getRepository('OCSOCSBundle:RoleScheduel')->findByUser($user->getId());
Said Kholov
  • 2,436
  • 1
  • 15
  • 22
Mourad MAMASSI
  • 849
  • 1
  • 11
  • 14
3

For Symfony 3.x

The most easy-peasy solution for me was to just turn on autowiring/autoconfiguring, and then injecting the service I needed via the constructor. Note that I have also allowed any controller to be injected as a service by setting resource: '../../src/AppBundle/*'

 #services.yml or config.yml
 services:
    _defaults:
        autowire: true
        autoconfigure: true
        public: false
    # Allow any controller to be used as a service
    AppBundle\:
        resource: '../../src/AppBundle/*'    
        # you can exclude directories or files
        # but if a service is unused, it's removed anyway
        exclude: '../../src/AppBundle/{Entity,Repository,Tests,DataFixtures,Form}'

Then in any service, you can inject & use the entity manager $em (or any other service/controller) via the constructor like this:

// class xyz
private $em;
// constructor
public function __construct(\Doctrine\ORM\EntityManager $em)  {
    $this->em = $em;
}
public function bar() {
    //Do the Database stuff
    $query = $this->em->createQueryBuilder();
    //Your Query goes here
    $result = $query->getResult();
}
Niket Pathak
  • 6,323
  • 1
  • 39
  • 51
2

for anyone who works with symfony3: u need to do the following inside config/services.yml in order to use doctrine in Service Container:

servicename_manager:
          class: AppBundle\Services\MyServiceClass
          arguments: [ "@doctrine.orm.entity_manager" ]
Achref Gassoumi
  • 1,035
  • 10
  • 20
2

in the Symfony 3.4. If you want to use Doctrine in a service you can do it: Only this method worked for me

services.yml:

YourBundle\PatchService\YourService:
      public: true
      arguments: [ '@doctrine.orm.entity_manager' ]

Service:

class YourService
{
    private $em;
    public function __construct($em)  {
        $this->em = $em;
    }

Controller:

use YourBundle\PatchService\YourService;

     /**
         * @Route("/YourController/",name="YourController")
         */
        public function indexAction()
        {
            $em = $this->getDoctrine()->getManager();
            $Notification = new  YourService($em);
yAnTar
  • 4,269
  • 9
  • 47
  • 73
pedram shabani
  • 1,654
  • 2
  • 20
  • 30
1

I am using Symfony 3.4. If you want to create a service in a bundle this works for me:

services:
 Vendor\YourBundle\Service\YourService:
   arguments:
     $em: '@doctrine.orm.entity_manager'

In your Service.php

<?php

namespace Hannoma\ElternsprechtagBundle\Service;

use Doctrine\ORM\EntityManager;
use Hannoma\ElternsprechtagBundle\Entity\Time;

class TimeManager
{
 protected $em;

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

}
Hannoma
  • 11
  • 2
0

Since 2017 and Symfony 3.3 you can register Repository as service, with all its advantages it has.

Your code would change like this.

1. Service configuration

# app/config/services.yml
services:
    _defaults:
        autowire: true

    ...\Service\:
       resource: ...\Service

2. Create new class - custom repository:

use Doctrine\ORM\EntityManagerInterface;

class YourRepository
{ 
    private $repository;

    public function __construct(EntityManagerInterface $entityManager)
    {
        $this->repository = $entityManager->getRepository(YourEntity::class);
    }

    public function find($id)
    {
        return $this->repository->find($id);
    }
}

3. Use in any Controller or Service like this

class dsdsf
{ 
    private $yourRepository;

    public function __construct(YourRepository $yourRepository)
    {
        $this->yourRepository = $yourRepository;
    }

    public function create()
    {
        $id = 10;
        $this->yourRepository->find($id);
    }
}

Do you want to see more code and pros/cons lists?

Check my post How to use Repository with Doctrine as Service in Symfony.

Tomas Votruba
  • 23,240
  • 9
  • 79
  • 115
  • Why not define it in your service config as an argument? `@=service("doctrine.orm.entity_manager").getRepository("Namespace\Entity")` – Will B. Nov 27 '17 at 15:08
  • 1
    Framework-agnostic PHP code over framework-coupled-config-yaml-specific knowledge. – Tomas Votruba Nov 28 '17 at 01:07
  • Fair enough, thank you. Sorry, I should have provided a link to the [Symfony expression usage](https://symfony.com/doc/current/components/expression_language/syntax.html) – Will B. Nov 28 '17 at 02:31