tanGee
tanGee

Reputation: 573

Injecting @session into EntityRepository

I wanted to override the default Doctrine\ORM\EntityRepository class in my Symfony2 project so that I can have access to the @session service so that all of my repositories have access to a certain session variable if it is set.

On investigation it appeared to be less simple than I had hoped, as the EntityRepository is instantiated from within the Doctrine\ORM\EntityManager, and this class is instantiated itself using a static "create" method.

I followed the answer in Injecting dependency into entity repository but have hit a roadblock in actually implementing the custom manager class (specifically where the answer's author says "But since you're making a custom entity manager, you can wire it up to the service container and inject whatever dependencies you need").

I have defined my overridden EntityManager class, with an overridden "create" function and have also overridden the "getRepository" function. It is in this function that I believe I need to add the session to the Repository as it is created using a "setSession" method on my overridden EntityRepository class, but I am unsure as to how to actually get the session into the manager in the first place, as the other constructor arguments for the EntityManager class (Connection $conn, Configuration $config, EventManager $eventManager) are supplied in the Symfony\Bundle\DoctrineBundle\DependencyInjection\DoctrineExtension "ormLoad" method.

I have also specified

doctrine.orm.entity_manager.class: Me\MyBundle\Doctrine\ORM\EntityManager

in my config.yml file.

How can I have Symfony use my custom EntityManager class when creating repositories, and inject the session into it as well?

Upvotes: 2

Views: 1669

Answers (3)

Yes Barry
Yes Barry

Reputation: 9876

In Symfony 4+ you can just make it a ServiceEntityRepository and with autowiring there's no need for any services.yaml changes.

namespace App\Repository;

use App\Entity\YourEntity;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Common\Persistence\ManagerRegistry;
use Symfony\Component\HttpFoundation\Session\SessionInterface;

class YourRepository extends ServiceEntityRepository
{
    private $session;

    public function __construct(ManagerRegistry $registry, SessionInterface $session)
    {
        $this->session = $session;
        parent::__construct($registry, YourEntity::class);
    }

    public function findSomethingUsingSession()
    {
        $someValue = $this->session->get('some_index');
        // ...
    }
}

Then in your controller (for example)

$repository = $this->getDoctrine()->getRepository(YourEntity::class);
$result = $repository->findSomethingUsingSession();

Or use dependency injection (recommended)

public function someAction(YourRepository $repository)
{
    $result = $repository->findSomethingUsingSession();
    // ...
}

Upvotes: -1

tanGee
tanGee

Reputation: 573

I ended up going with something slightly different:

I overrode the doctrine.orm.entity_manager.class parameter with my custom class which simple extended the default class with an additional $session parameter (complete with getter and setter), along with overridden create and getRepository functions (to return instances of my class instead of the default.

I then overrode the EntityRepository class and implemented a "getSession" method which returned

$this->_em->getSession();

and finally, in a custom event listener which has access to the entity manager, I called

$this->entityManager->setSession($session);

which gave me access to the session from every repository.

Upvotes: 1

Jovan Perovic
Jovan Perovic

Reputation: 20201

Florian, here, explained how to create repository via service:

my_service:
    class: Doctrine\Common\Persistence\ObjectRepository
    factory_service: doctrine # this is an instance of Registry
    factory_method: getRepository
    arguments: [ %mytest.entity% ]

You could add calls to invoke setSession (as deferred DI):

my_service:
    ...
    calls:
        - [setSession, ["@session"]]

Is this you're trying to do?

Upvotes: 3

Related Questions