Domain driven design PHP存储库模式实现问题

Domain driven design PHP存储库模式实现问题,domain-driven-design,repository-pattern,ddd-repositories,Domain Driven Design,Repository Pattern,Ddd Repositories,存储库应该从服务调用返回什么? 例如,一个实体(或实体集合)或对其自身的引用,可以用来访问包含实体集合的属性 以以下示例代码为例: $user = $userRepository->findById(1); 或 我认为在大多数代码中,这样的调用会返回用户实体对象或用户集合实体 对我来说,这似乎有点奇怪,从一个方向来说,存储库将直接返回对象,但从另一个方向来说,它将在对对象执行操作之前保持它们的状态。以此示例代码为例: $user = $factory->make('user');

存储库应该从服务调用返回什么?

例如,一个实体(或实体集合)或对其自身的引用,可以用来访问包含实体集合的属性

以以下示例代码为例:

$user = $userRepository->findById(1);

我认为在大多数代码中,这样的调用会返回用户实体对象或用户集合实体

对我来说,这似乎有点奇怪,从一个方向来说,存储库将直接返回对象,但从另一个方向来说,它将在对对象执行操作之前保持它们的状态。以此示例代码为例:

$user = $factory->make('user');
$user->setName($array_data['name']);

$repo->add($user);
$repo->save();
就是这样做的吗

在检索方面,我想我希望看到更像这样的东西:

$users = $userRepository->findAll(); // Returns $userRepository reference

foreach($users->collection() as $user) {
    // Do some operations, or whatever
}

$users->save();
或者,对于只读需求:

$users = $userRepository->findAll();
$users = $users->collection(); // Returns User Entities held in state
如果能澄清为什么会这样或那样做,我们将不胜感激

工厂在域内属于何处?

它应该作为映射器对象的依赖项注入吗?似乎还必须有来自控制代码/服务层的工厂访问权限,才能创建要提交到存储库的实体

这引出了我的下一个问题

从控制类/服务层创建新实体的首选方法是什么?

我看到过使用Factory对象,如下所示:

$user = $factory->make('user');
$user->setName($array_data['name']);

$repo->add($user);
$repo->saveFromArray($array_data);
以及内置的存储库方法,如下所示:

$user = $factory->make('user');
$user->setName($array_data['name']);

$repo->add($user);
$repo->saveFromArray($array_data);
在第二个示例中,$array_数据将通过存储库转发到映射器,映射器随后将执行保存。当然,在这两个示例中,都会事先检查数据源是否存在重叠记录


我想首选第一种方法?这似乎是一种更面向对象的方法。

您有很多问题

存储库应该从服务调用返回什么

始终聚合根(AR)。AR设计非常重要,但与存储库无关。存储库方法根据域的需要返回一个或多个对象。没有用户集合Enitity,有一个用户列表(在php中可能是一个数组),不要让事情复杂化

域存储库应仅用于域需要(读或写)。返回整个对象,存储库不返回AR的片段,而是返回整个AR。我再次提到AR设计非常重要

工厂在域内属于哪里

在需要的地方。我不使用工厂,最多我有一个工厂方法,但即使是用于恢复目的(如果我使用的是纪念品)。您不必使用工厂来创建域对象

从控制类/服务层创建新实体的首选方法是什么

最简单的方法。对于可能99%的情况,您将使用“new”操作符。只有当工厂为特定实体带来具体利益时,才使用工厂

映射器从不执行保存,因为它是映射器。只有存储库才能执行持久性工作。映射程序将数据从一个模型“转换”或复制到另一个模型。您可以使用映射器将域对象映射到要持久化并返回的某些数据模型