Symfony领域事件

6
我正在尝试在Symfony2项目中实现领域驱动设计,并遇到了一些问题。在阅读了一些关于领域模型的文章后,我发现:

  • 我应该将所有业务逻辑放入我的领域模型(实体)中。
  • 需要执行并不属于领域逻辑的应用程序级别的内容,可以通过领域事件来触发(发送电子邮件、将某些消息放入队列等)。

幸运的是,Symfony提供了事件,但问题在于 - 我无法从我的实体中引发事件。Symfony文档建议使用DI将调度器注入到引发事件的类中。

http://symfony.com/doc/current/book/internals.html#passing-along-the-event-dispatcher-object

Symfony实体是可实例化的,而非可注入的。 目前我能看到两种方式: 1)像这样为实体提供事件分发器
class FooEntity
{
    protected $dispatcher = null;

    public function setEventDispatcher(EventDispatcher $dispatcher)
    {
        $this->dispatcher = $dispatcher;
    }
}

2)从服务中引发事件(而不是从实体中引发事件)。

这些选项都不太好,因为它们似乎违背了领域模型的思想。请问您能否指点我正确的方向?

2个回答

2
你所说的Symfony实体,是否指Doctrine 2实体?如果是,可以按以下方式在新对象和从数据库加载的旧对象上设置服务:

原型作用域服务

原型作用域中的服务总是在获取时重新创建。不需要使用new FooEntity来创建对象,而是使用$container->get('foo_entity')
在YAML语法中,你应该这样定义服务:
foo_entity:
  class: FooEntity
  calls: 
    - [setEventDispatcher, [@event_dispatcher]]
  scope: prototype

这将处理新实体。对于现有实体,您需要一个“postLoad”事件侦听器。按照以下方式创建事件侦听器:http://symfony.com/doc/current/cookbook/doctrine/event_listeners_subscribers.html。使侦听器监听“postLoad”事件。将事件分派程序注入到侦听器服务中,并使用侦听器服务在实体上设置事件分派程序。请注意,侦听器服务将在加载任何实体后触发,不仅仅是FooEntity,因此您需要进行类型检查。

我认为实体本身不应该拥有一切。它只需要知道如何与自己协作即可。如果findBy(array('id'=>$idvalue))不足够,Repository应该提供帮助器,但已经很强大了。我发现,做一些专门的EntityManagers是业务逻辑的最佳场所。 - renoirb

2
这里的想法是提供实现DDD范例的路径。
我不想掩盖@magnusnordlander的回答,我会采用他所说的方法。
以下是我的一些观察:
我认为实体本身不应该拥有一切。无论如何,这肯定不是DDD人们的说法。[Doctrine2]实体只应负责关系(一个具有不同变化的实体<= 这实际上是我卡了一段时间的问题)和聚合根
Doctrine实体只需知道如何与自身配合工作。
但是,要获取数据或处理数据,还有其他东西可以使用: 存储库 提供帮助程序以获取比快速的findBy(array('id'=>$idvalue))更复杂的查找器(这是 Entity/ Assocation/ Annotation无法覆盖的)确实是一个非常方便的好东西。
我个人尝试构建所有查询,并意识到EntityManager已经非常好,开箱即用。在我看来,大多数情况下,如果您不能使用查询或查询生成器,则更好。
所有这些都涉及业务逻辑...
最后一件事,您要搜索的内容必须基本上缩小控制器。
例如,FooManager就是业务逻辑所在的地方(如果我没有弄错的话)。
我在那个问题上找到了一笔宝贵的信息(此博客),包括以下内容:

如果您有任何想法要补充,请将这个答案设置为社区Wiki。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接