Symfony观察者模式 - 如何在设置实体属性时调度自定义事件?

时间:2018-02-09 08:47:06

标签: php symfony events doctrine observer-pattern

每次调用某个实体设置器时,有没有办法调度自定义事件?

每次更改某个实体属性时,我实际上需要更改不相关实体的某些值。因此,为了分离关注点和解耦对象,我想用观察者模式来做这件事。我不想在某些教义事件中执行此操作,例如'preUpdate'或类似事件,因为它们仅在刷新实体时触发,但我需要立即更改此值以确保这两个值始终保持同步。

由于将任何服务注入实体是不好的做法,我不知道如何做到这一点?

有什么建议吗?

2 个答案:

答案 0 :(得分:1)

使用事件调度程序

将包含您的信息的活动

class UpdateEntityEvent extends Event {
     private $myEntity;
     private $newValue;

     public function __construct(Entity $entity, Whatever $newValue){
         $this->myEntity = $entity;
         $this->newValue = $newValue;
    }
  // [...] getters
}

你的听众

class UpdateMyEntityEventListener
{
    public function updateCertainProperty(UpdateMyEntityEvent $event)
    {
        // Do what you want here :D
    }
}

一些配置

 kernel.listener.updateMyEntity:
     class: Acme\AppBundle\EventListener\UpdateMyEntityEventListener
     tags:
         - { name: kernel.event_listener, event: updateMyEntity, method: updateCertainProperty }

我们避免使用一些硬编码字符串,让我们将事件名称放在一个常量

class MyEntityEvents 
{
    const UPDATE = 'updateMyEntity';
}

然后在您的控制器中

public function updateAction()
{
    // [...]
    $event = new UpdateMyEntityEvent($entity, $whatever);
    $dispatcher = $this->get('event_dispatcher')->dispatch( MyEntityEvents::UPDATE, $event);

答案 1 :(得分:1)

如果你想使用观察者模式,你必须以某种方式自己实现它。正如您所指出的,只有在触发刷新操作而不是之前,Doctrine才会计算实体的变更集。话虽这么说,但正如Doctrine提出的那样alternative tracking policiesNOTIFY跟踪政策行为完全取决于您希望实现的目标。

我并不是说您应该更改实体的跟踪策略,但是您可以利用现有的接口来实现您的观察者模式。为此,正如in this section of the documentation所解释的那样,您观察到的实体需要实现NotifyPropertyChanged接口。

从那里你可以直接在另一个实体中实现PropertyChangedListener接口(或者使用一个特定的服务,例如在postLoad事件中将自己添加为你的实体的监听器?)。这主要取决于您的实体之间的关系以及如何将您的侦听器附加到实现NotifyPropertyChanged的实体。

请注意,如果这样做,Doctrine的UnitOfWork会自动将自己挂钩作为您实体的监听器,但只要您不添加{{1},它仍将依赖自动变更集计算注释。