Tim*_*tle 3 datamapper service-layer doctrine-orm
我不久前问了一个类似的问题:使用数据映射器模式,实体(域对象)应该知道Mapper吗?但是,它是通用的,我真的很感兴趣如何用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搜索a Vote而不必加载整个集合?
我绝对倾向于使用轻型服务层; 但是,有没有更好的方法来处理Doctrine2这类事情,或者我是朝着正确的方向前进?
我投票支持服务层.我经常努力尝试在实体本身添加尽可能多的逻辑,并且只是让自己感到沮丧.无法访问EntityManager,您根本无法执行查询逻辑,当您只需要几条记录时,您会发现自己使用了大量的O(n)操作或延迟加载整个关系集(这是超级的与DQL提供的所有优势相比,它是蹩脚的.
如果你需要一些帮助得到过的想法,贫血域模型始终是一个反模式,请参阅本演示由马修·威尔O'Phinney或这个问题.
虽然我可能会误解术语,但我并不完全相信实体必须是域模型中允许的唯一对象.我很容易认为实体对象及其服务的总和构成了模型.我认为,当您最终编写一个几乎不关注关注点分离的服务层时,就会出现反模式.
我经常想到让所有实体对象将一些方法代理到服务层:
public function addVote($vote)
{
   $this->_service->addVoteToThing($vote, $thing);
}
但是,由于Doctrine没有任何类型的对象水合回调事件系统,我还没有找到一种优雅的方式来注入服务对象.
我的建议是将所有查询逻辑放入EntityRepository,然后从中创建一个类似于的接口:
class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}
这样您就可以在服务对象的单元测试中使用接口,并且不需要依赖EntityManager.
| 归档时间: | 
 | 
| 查看次数: | 2357 次 | 
| 最近记录: |