Doctrine2 最佳实践,实体应该使用服务吗?

发布于 2024-10-08 04:23:36 字数 1601 浏览 2 评论 0原文

我不久前问过类似的问题: 使用数据映射器模式,实体(域对象)应该了解映射器吗?但是,它是通用的,我真的很感兴趣如何使用 Doctrine2 专门完成一些事情< /强>。

下面是一个简单的示例模型:每个 Thing 都可以有来自 UserVote,一个 User 可以投票超过一次投票,但仅最后一次投票有效。由于其他数据(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 仅具有最后一个 < code>投票计数是Thing应该确保的事情,而则不然一些服务层

因此,为了将其保留在模型中,新的 Thing 函数:

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

那么如何从域模型中删除 Vote 我应该放松一下吗投票::setThing() 接受NULL?我是否应该涉及某种可以让 Thing 用来删除投票的服务层?一旦投票开始累积,foreach 就会变得很慢 - 如果使用服务层来允许 Thing 搜索 Vote 而无需必须加载整个集合?

我绝对倾向于使用轻服务层;但是,有没有更好的方法来使用 Doctrine2 处理此类事情,或者我正朝着正确的方向前进吗?

I asked a similar question a while back: Using the Data Mapper Pattern, Should the Entities (Domain Objects) know about the Mapper? However, it was generic and I'm really interested in how to accomplish a few things with Doctrine2 specifically.

Here's a simple example model: Each Thing can have a Vote from a User, a User may cast more than one Vote but only the last Vote counts. Because other data (Msssage, etc) is related to the Vote, when the second Vote is placed the original Vote can't just be updated, it needs to be replaced.

Currently Thing has this function:

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

And Vote takes care of setting up the relationship:

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

It seems to me that ensuring a User only has the last Vote counted is something the Thing should ensure, and not some service layer.

So to keep that in the Model, the new Thing function:

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

So how do I remove the Vote from within the Domain Model? Should I relax Vote::setThing() to accept a NULL? Should I involve some kind of service layer that Thing can use to remove the vote? Once the votes start accumulating, that foreach is going to be slow - should a service layer be used to allow Thing to search for a Vote without having to load the entire collection?

I'm definitely leaning toward using a light service layer; however, is there a better way to handle this type of thing with Doctrine2, or am I heading in the right direction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

江挽川 2024-10-15 04:23:36

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

如果您需要一些帮助来克服贫血域模型始终是反模式的想法,请参阅 Matthew Weier O'Phinney 的演示这个问题

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

我经常考虑让所有实体对象将某些方法代理到服务层:

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

但是,由于 Doctrine 没有任何关于对象水合作用的回调事件系统,我还没有找到一种优雅的方式来注入服务目的。

I vote for the service layer. I've often struggled with trying to add as much logic on the Entity itself, and simply frustrated myself. Without access to the EntityManager, you're simply not able to perform query logic, and you'll find yourself using a lot of O(n) operations or lazy-loading entire relationship sets when you only need a few records (which is super lame when compared to all the advantages DQL offers).

If you need some assistance getting over the idea that the Anemic Domain Model is always an anti-pattern, see this presentation by Matthew Weier O'Phinney or this question.

And while I could be misinterpreting the terminology, I'm not completely convinced that Entities have to be the only objects allowed in your Domain Model. I would easily consider that the sum of Entity objects and their Services constitutes the Model. I think the anti-pattern arises when you end up writing a service layer that pays little to no attention to separation of concerns.

I've often flirted with the idea of having all my entity objects proxy some methods to the service layer:

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

However, since Doctrine does not have any kind callback event system on object hydration, I haven't found an elegant way to inject the service object.

如何视而不见 2024-10-15 04:23:36

我的建议是将所有查询逻辑放入 EntityRepository 中,然后从中创建一个接口,就像这样:

class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}

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

My advice would be to put all the query logic into an EntityRepository and then make an interface out of it sort of like:

class BlogPostRepository extends EntityRepository implements IBlogPostRepository {}

that way you can use the interface in your unit-tests for the service objects and no dependency on the EntityManager is required.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文