Well in my current application, my front controller class is passing each repository and service classes to the constructor of my application controller classes. It works fine for simple controllers, but can quickly become complicated. An example of such application controller constructor looks like this.
class UserProfileController extends ApplicationController{
private $userProfileRepository;
private $contactRepository;
private $authenticationService;
public function __construct(UserRepository $userRepository, UserProfileRepository $userProfileRepository, ContactRepository $contactRepository, AuthenticationService $authenticationService){
parent::__construct($userRepository);
$this->userProfileRepository = $userProfileRepository;
$this->contactRepository = $contactRepository;
$this->authenticationService = $authenticationService;
}
}
The fact is that the user profile pages need to display a lot of information, and it needs several repositories to complete the task(I actually leave out Posts, Comments and other repositories to make it less scary, but its still a lot). Its very inconvenient, and the constructors of these controller classes can be easily polluted if multiple repositories and services need to be injected. Also the UserProfileRepository and ContactRepository may need to eager load User object using UserRepository, this can quickly become a royal mess.
I know that in Doctrine, however, there is an EntityManager sitting on top of the repositories. With Doctrine, you can simply pass an EntityManager class to the constructor of controllers, and it will be able to create any repositories given that they are valid. Below is how the code can be refactored using Doctrine’s EntityManager:
class UserProfileController extends ApplicationController{
private $authenticationService;
public function __construct(EntityManager $entityManager, AuthenticationService $authenticationService){
parent::__construct($entityManager);
$this->authenticationService = $authenticationService;
}
}
The controller’s constructor now looks a lot cleaner, and this way if I want to get a list of users, user profiles and their contact information, I can just call the methods on entity manager to retrieve the corresponding repositories:
$userRepository = $this->entityManager->getRepository("UserRepository");
$userProfileRepository = $this->entityManager->getRepository("UserProfileRepository");
$userProfileRepository = $this->entityManager->getRepository("ContactRepository");
From first glance, it looks elegant and the EntityManager can encapsulate dependencies between repositories too. However, I cant help but notice that the entity manager is now effectively acting like a service locator. Is it just me or anyone else feels this way too? Since we all know that service locator is an anti-pattern, and we should rely on Dependency Injection. Does this mean that Doctrine’s Entity Manager is not a good thing to use despite the fact that it does make things simpler? What do you think?