genesst
genesst

Reputation: 1431

Dependency Injection best practices in Symfony2

In Symfony2 (2.8 in this case) what is considered best practice when injecting services into another service?

/**
 * Checker constructor.
 * @param EntityManager $em
 * @param EventDispatcherInterface $dispatcher
 */
public function __construct(EntityManager $em, EventDispatcherInterface $dispatcher)
{
    $this->repoUser = $em->getRepository(User::class);
    $this->repoPurchase = $em->getRepository(Purchase::class);
    $this->repoTicket = $em->getRepository(Ticket::class);
    $this->dispatcher = $dispatcher;
}

or

/**
 * Checker constructor.
 * @param UserRepository $ur
 * @param PurchaseRepository $pr
 * @param TicketRepository $tr
 * @param EventDispatcherInterface $dispatcher
 */
public function __construct(UserRepository $ur, PurchaseRepository $pr, TicketRepository $tr, EventDispatcherInterface $dispatcher)
{
    $this->repoUser = $ur;
    $this->repoPurchase = $pr;
    $this->repoTicket = $tr;
    $this->dispatcher = $dispatcher;
}

or use setters explicitly and set arguments to them individually in services.yml?

I wonder what's the performance part of the equation as well.

Upvotes: 3

Views: 386

Answers (1)

Maksym  Moskvychev
Maksym Moskvychev

Reputation: 1674

There are pros and cons in both cases.

  • In terms of performance, both options are equal, because you get instances of repositories only when you request instance of your service. Doesn't matter you do it manually, or it's done automatically by DI. As mentined here,

    The container is lazy: it doesn't instantiate a service until (and unless) you ask for it.

  • If you are going to cover your service with Unit tests - then option 2 is definatelly better, because you don't need to mock $em->getRepository() calls in the beginning of the test.

  • Benefits of individual setters - is also related to unit testing. For example, for one test case you need only one dependency, for another test case - another dependency. So, you can use setters inside of test to set mocks, and you don't need to pass all mocks into constructor.

Upvotes: 7

Related Questions