Repository query conditions, dependencies and DRY
Posted
by
vFragosop
on Programmers
See other posts from Programmers
or by vFragosop
Published on 2013-10-24T02:47:34Z
Indexed on
2013/10/24
4:07 UTC
Read the original article
Hit count: 189
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
:
- An admin interface which may list all users
- Public front-end which may list all users
- An account authenticated API which should only list it's own users
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:
1. Should I create an 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)
2. Should I put it as a method on 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.
3. Should I query 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.
4. Or am I missing the point completely?
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.
© Programmers or respective owner