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