To keep it simple, let's suppose an application which has Accounts
and Users
. Each account may have any number of users. There's also 3 consumers of UserRepository
:
Assuming UserRepository
is something like this:
class UsersRepository extends DatabaseAbstraction {
private function query() {
return $this->database()->select('users.*');
}
public function getAll() {
return $this->query()->exec();
}
// IMPORTANT:
// Tons of other methods for searching, filtering,
// joining of other tables, ordering and such...
}
Keeping in mind the comment above, and the necessity to abstract user querying conditions, How should I handle querying of users filtering by account_id
? I can picture three possible roads:
AccountUsersRepository
?class AccountUsersRepository extends UserRepository {
public function __construct(Account $account) {
$this->account = $account;
}
private function query() {
return parent::query()
->where('account_id', '=', $this->account->id);
}
}
This has the advantage of reducing the duplication of UsersRepository
methods, but doesn't quite fit into anything I've read about DDD so far (I'm rookie by the way)
AccountsRepository
?class AccountsRepository extends DatabaseAbstraction {
public function getAccountUsers(Account $account) {
return $this->database()
->select('users.*')
->where('account_id', '=', $account->id)
->exec();
}
}
This requires the duplication of all UserRepository
methods and may need another UserQuery
layer, that implements those querying logic on chainable way.
UserRepository
from within my account entity?class Account extends Entity {
public function getUsers() {
return UserRepository::findByAccountId($this->id);
}
}
This feels more like an aggregate root for me, but introduces dependency of UserRepository
on Account
entity, which may violate a few principles.
Maybe there's an even better solution?
Footnotes: Besides permissions being a Service concern, in my understanding, they shouldn't implement SQL query but leave that to repositories since those may not even be SQL driven.
Fetching all users belonging to an account is more of an UI concern. My suggestion is use your MVC controller(like AccountAdminController?) invoke the UserRepository.findByAccountId() directly.
I think Aggregates should be returned only by its own repository.