Question

what is the best practice for injecting repositories, entity managers to a service?

I figured I can do it in at least three ways.

1. Injecting repositories, managers through the constructor

This way the service can be covered with tests quite easily. All you need is to pass mocked dependencies to the constructor and you're ready.

class TestService
{
    public function __construct(MyEntityRepository $my, AnotherEntityRepository $another, EntityManager $manager)
    {
        $this->my = $my;
        $this->another = $another;
        $this->manager = $manager;
    }

    public function doSomething()
    {
        $item = $this->my->find(<...>);
        <..>
        $this->manager->persist($item);
        $this->manager->flush();
    }
}

2. Passing just the EntityManager

This is a bit more difficult to test if you need like 4 repositories from the same manager. I figured this way you have to mock manager's getRepository calls.

class TestService
{
    public function __construct(EntityManager $manager)
    {
        $this->manager = $manager;
    }

    public function doSomething()
    {
        $item = $this->manager->getRepository('my')->find(<...>);
        <..>
        $this->manager->persist($item);
        $this->manager->flush();
    }
}

3. Passing the whole registry

This way you don't get circular reference exception with doctrine event subscribers, but it's harder to mock everything.

Also this is the only way sensiolabs insights doesn't give me an architectural violation for injecting EntityManager.

class TestService
{
    public function __construct(RegistryInterface $registry)
    {
        $this->doctrine = $registry;
    }

    public function doSomething()
    {
        $item = $this->registry->getManager()->getRepository('my')->find(<...>);
        <..>
        $this->registry->getManager()->persist($item);
        $this->registry->getManager()->flush();
    }
}

What is the best practice to do this and why?

Was it helpful?

Solution

I always try to inject my services as specific as possible.

Which means I always inject repositories since that is easier when writing tests. Otherwise you have to mock the registry and or manager too.

OTHER TIPS

I know this is old but I just thought I'd add my 2 cents. I follow what Matthias Noback says in these two blog posts:

So I inject the specific repository whenever I need to find an entity, but I also inject the ManagerRegistry if I need to call flush, persist or remove, because otherwise you have to put proxy functions for them in all your repositories.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top