I have modeled my application using multiple ‘user’ domain objects.
- Candidate
- Recruiter
- Administrator
Each entity extends from an AbstractUser
implementing UserInterface
.
interface UserInterface
{
public function getEmail();
public function setEmail($email);
public function getPassword();
public function setPassword($password);
}
They all have their own a services CandidateService
, AdminService
etc implementing UserServiceInterface
interface UserServiceInterface
{
public function getUserByEmail();
}
My problem arises when I need to fetch a user by their email address (say PasswordResetService
) I am unable to determine which service I should be calling as the email could be either of them. I am also using mongoDB so I cannot simply run a native query joining the ‘tables’.
My current thought is that I have to inject each service into the PasswordResetService
and call getUserByEmail()
on each of them until I get my desired user.
class PasswordResetService
{
public function getUserByEmail($email)
{
$user = $this->userService->getUserByEmail($email);
if ($user) return $user;
$user = $this->recruiterService->getUserByEmail($email);
if ($user) return $user;
// etc ...
}
}
From a design perspective the above seems to me like a poor approach as should I add a new user ‘type’ I would need to update the password service also.
Is there a better way of achieving this?
3
I would approach this by having a top level UserService that doesn’t care what type of user it’s dealing with.
If it gets a request for a user by email, it can look up on the database which type of user is correct and delegate the request to the correct service. This may sound a little inefficient, but used with an appropriate query caching later it’s actually fine.
Other methods that are passed a user object could perhaps use double dispatch to forward the request to the correct service object., thus eliminating the need to hit the database for these operations.