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

8 Answers 8

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.

Sign up to request clarification or add additional context in comments.

6 Comments

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"
Yes, I meant that. You're getting this error because you're not injecting an EntityManager from the container. I'll update my answer.
@user1075510: If this is the best answer, please checkmark it.
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
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.
|
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 :)

4 Comments

The example class that you posted isn't valid PHP. Correct your example, and I'll give you an upvote.
You missed 2 semi colons
You cannot call any functions outside of a method scope (e.g. right in the class). Calling $this->em->createQueryBuilder() would never work, because referring to $this is invalid at this point.
little typo protected $em: should be protected $em;
3

Please try this code:

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

 $rolescheduels=$em->getRepository('OCSOCSBundle:RoleScheduel')->findByUser($user->getId());

Comments

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

Comments

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" ]

Comments

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

Comments

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

}

Comments

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.

3 Comments

Why not define it in your service config as an argument? @=service("doctrine.orm.entity_manager").getRepository("Namespace\Entity")
Framework-agnostic PHP code over framework-coupled-config-yaml-specific knowledge.
Fair enough, thank you. Sorry, I should have provided a link to the Symfony expression usage

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.