Symfony: Inject Doctrine Repositories in Controllers

Nebojša Kamber
May 13, 2018 · 2 min read

I’ve come across a cool pattern in Symfony 4 — injecting repositories instead of EntityManager

// Before
public function showAllUsers(EntityManagerInterface $em)
{
$users = $em->getRepository(User::class)->findAll();

return $this->json($users);
}

// After
public function showAllUsers(UserRepository $userRepository)
{
$users = $userRepository->findAll();

return $this->json($users);
}

In the latter, we keep the scope limited only to the repository we need, not holding on to the whole EntityManager.
It's possible because all your repositories are automatically registered as services and hence can be autowired.
Previous Symfony versions allowed you to register repositories as services manually and event that was tedious, because it required a custom factory etc.

Since EntityManager is mostly used for persisting and deleting entities, you can add a few helper methods to your repository(ies):

/**
* @param object $entity
*/
public function save($entity)
{
$this->_em->persist($entity);
$this->_em->flush();
}

/**
* @param object $entity
*/
public function delete($entity)
{
$this->_em->remove($entity);
$this->_em->flush();
}

$this->_em property is already available, if you're extending the default ServiceEntityRepository

Then, you can shorten your create/delete controllers as well:

// Before
public function createUser(Request $request, EntityManagerInterface $em)
{
$user = new User();
// request handling, form validation..

$em->persist($user);
$em->flush();

return $this->json($user);
}

public function deleteUser(User $user, EntityManagerInterface $em)
{
$em->remove($user);
$em->flush();

return new Response('', Response::HTTP_NO_CONTENT);
}

// After
public function createUser(Request $request, UserRepository $userRepository)
{
$user = new User();
// request handling, form validation..

$userRepository->save($user);

return $this->json($user);
}

public function deleteUser(User $user, UserRepository $userRepository)
{
$userRepository->delete($user);

return new Response('', Response::HTTP_NO_CONTENT);
}

Originally published at Nebojša.dev.

EDIT: first version of the post did not utilize the DI for fetching the EntityManager and did an unfair comparison. This is corrected and the actual difference between these two approaches is probably trivial now.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch

Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore

Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store