【问题标题】:Repository query conditions, dependencies and DRY存储库查询条件、依赖关系和 DRY
【发布时间】:2013-10-24 02:59:04
【问题描述】:

为了简单起见,让我们假设一个应用程序具有AccountsUsers。每个帐户可以有任意数量的用户。 UserRepository还有3个消费者:

  • 可以列出所有用户的管理界面
  • 可以列出所有用户的公共前端
  • 一个账户认证的 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);
    }
}

这对我来说更像是一个聚合根,但引入了 UserRepositoryAccount 实体的依赖,这可能违反了一些原则。

4。还是我完全没有抓住重点?

也许有更好的解决方案?


脚注:在我的理解中,除了权限是一个服务问题之外,他们不应该实现 SQL 查询,而是将其留给存储库,因为它们甚至可能不是 SQL 驱动的。

【问题讨论】:

    标签: php domain-driven-design repository-pattern dry ddd-repositories


    【解决方案1】:

    获取属于某个帐户的所有用户更多的是 UI 问题。我的建议是使用您的 MVC 控制器(如 AccountAdminController?)直接调用 UserRepository.findByAccountId()。

    我认为聚合应该只由它自己的存储库返回。

    【讨论】:

    • 补充一点:通过创建自定义存储库方法,您可以提取领域特征,这有助于使代码库中的业务(领域)逻辑更加清晰。例如。 UserRepository.findByAccountId() 比 UserRepository.findBy($query) 更好,因为它显示了用户和代理之间的关系。每次需要显示属于某个帐户的所有用户时,都无需创建自定义查询对象。
    • 现在我正在考虑,将其视为 UI 问题非常有意义。虽然,它提出了另一个问题:由于除了account_id 之外,我们还有复杂的动态查询,基于用户输入,我是否应该将我的存储库视为围绕IQuery 对象的某种装饰器?
    • @vFragosop 我想在构建动态查询时使用标准对象,例如 UserRepository.findBy(UserCriteria criteria)。 IQuery对象在php中有特殊含义吗?
    • 实际上并非如此,IQuery 我的意思是用于构建 SQL 查询的接口。我昨天确实读过一些关于标准的东西,但我真的不知道存储库如何在不创建更多类或依赖项的情况下将标准转换为LEFT JOIN b WHERE b.foo = bar 之类的东西。 (PHP 在 DDD 示例和模式实现方面缺乏很多)
    • @vFragosop 在最简单的情况下(没有 orm 框架),您可以根据条件构建 sql,例如“ if criteria.getEqFoo is not null then sql = sql + 'LEFT JOIN b WHERE b.foo = ' + criteria.getEqFoo()"
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-06-21
    • 2020-06-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-11-17
    • 2019-12-13
    相关资源
    最近更新 更多