为了简单起见,让我们假设一个具有Accounts
和Users
的应用程序。每个帐户可以有任意数量的用户。还有 3 个消费者UserRepository
:
- 可以列出所有用户的管理界面
- 公共前端,可以列出所有用户
- 经过帐户身份验证的 API,应仅列出自己的用户
假设UserRepository
是这样的:
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...
}
牢记上面的评论,以及抽象用户查询条件的必要性,我应该如何处理按account_id
过滤的用户的查询?我可以想象三条可能的道路:
1. 我应该创建一个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);
}
}
这具有减少UsersRepository
方法重复的优点,但不太适合我到目前为止读到的有关DDD的任何内容(顺便说一下,我是新手)
2. 我应该把它作为一种方法放在AccountsRepository
上吗?
class AccountsRepository extends DatabaseAbstraction {
public function getAccountUsers(Account $account) {
return $this->database()
->select('users.*')
->where('account_id', '=', $account->id)
->exec();
}
}
这需要复制所有UserRepository
方法,并且可能需要另一个UserQuery
层,以可链接的方式实现这些查询逻辑。
3. 我应该从我的账户实体内查询UserRepository
吗?
class Account extends Entity {
public function getUsers() {
return UserRepository::findByAccountId($this->id);
}
}
这对我来说更像是一个聚合根,但引入了UserRepository
对Account
实体的依赖,这可能会违反一些原则。
4.还是我完全错过了重点?
也许有更好的解决方案?
脚注:除了权限是一个服务问题之外,在我的理解中,他们不应该实现SQL查询,而是将其留给存储库,因为这些存储库甚至可能不是SQL驱动的。
获取属于某个帐户的所有用户更像是一个 UI 问题。我的建议是使用你的MVC控制器(如AccountAdminController?)直接调用UserRepository.findByAccountId()。
我认为聚合应该只由它自己的存储库返回。