我不久前问了一个类似的问题: 使用数据映射器模式,实体(域对象)是否知道映射器? 但是,这是通用的 我对如何专门使用Doctrine2完成一些事情很感兴趣.

这是一个简单的示例模型:每个 Thing 可以有一个 Vote 来自 User, , 一个 User 可能会施放多个 Vote 但只有最后 Vote 计数。因为其他数据(Msssage, ,等)与 Vote, ,第二 Vote 放置原始 Vote 不能只是更新,需要更换。

目前 Thing 具有此功能:

public function addVote($vote)
{
  $vote->entity = $this;
}

Vote 照顾建立关系:

public function setThing(Model_Thing $thing)
{
  $this->thing = $thing;
  $thing->votes[] = $this;
} 

在我看来,确保 User 只有最后一个 Vote 计数是 Thing 应确保,并且 没有某些服务层.

因此,为了将其保持在模型中 Thing 功能:

public function addVote($vote)
{
  foreach($this->votes as $v){
    if($v->user === $vote->user){
      //remove vote
    }
  }
  $vote->entity = $this;
}

那么我如何删除 Vote 从域模型中? 我应该放松 Vote::setThing() 接受 NULL?我应该涉及某种服务层 Thing 可以用来删除投票吗?一旦投票开始积累, foreach 要慢 - 如果使用服务层允许 Thing 搜索一个 Vote 不必加载整个系列?

我绝对倾向于使用轻型服务层。然而, 有没有更好的方法来处理这种类型的方法,或者我朝正确的方向前进?

有帮助吗?

解决方案

我投票支持服务层。我经常努力地尝试在实体本身上增加逻辑,而只是让自己感到沮丧。如果没有访问EntityManager的访问,您根本无法执行查询逻辑,并且您会发现自己使用大量O(n)操作或懒惰加载整个关系集时,只需要几个记录(这是超级记录)与DQL提供的所有优势相比,la脚。

如果您需要一些协助来克服贫血域模型始终是反庞大的想法,请参见 这个演示文稿 由Matthew Weier O'Phinney或 这个问题.

尽管我可能会误解术语,但我并不完全相信实体必须是您域模型中唯一允许的对象。我很容易地考虑到实体对象及其服务的总和构成了模型。我认为,当您最终编写一个几乎不关注关注点分离的服务层时,就会出现反故事。

我经常对将所有实体对象代表某些方法来服务层的想法:

public function addVote($vote)
{
   $this->_service->addVoteToThing($vote, $thing);
}

但是,由于学说在对象水合上没有任何类似的回调事件系统,因此我没有找到一种优雅的注入服务对象的方法。

其他提示

我的建议是将所有查询逻辑放入实体中,然后从中制成一个界面:

class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}

这样,您可以将单元测试中的接口用于服务对象,并且不需要对EntityManager的依赖。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top