Doctrine EventListener onFlush不保存原始实体

时间:2015-12-17 19:04:09

标签: symfony doctrine-orm flush event-listener

我一直在努力解决烦人的问题。我试图创建与过期的InventoryItems相关联的通知实体。

这些InventoryItems是为用户自动生成的,但用户可以编辑它们并单独设置它们的到期日期。保存后,如果InventoryItem具有到期日期,则会生成通知实体并将其关联。因此,当实体更新时会创建这些通知实体,因此onPersist事件将无法工作。

一切似乎都运行良好,并且在按预期保存InventoryItem时会生成通知。唯一的问题是,当第一次创建通知时,即使它已正确保存,也不会保存对InventoryItem的更改。这是创建了具有正确到期日期的通知,但有效期未保存在InventoryItem上。

这是我的onFlush代码:

 public function onFlush(OnFlushEventArgs $args)
{
    $em  = $args->getEntityManager();
    $uow = $em->getUnitOfWork();
    foreach ($uow->getScheduledEntityUpdates() as $entity) {
        if ($entity instanceof NotificableInterface) {
          if ($entity->generatesNotification()){
              $notification = $this->notificationManager->generateNotificationForEntity($entity) ;
              if ( $notification ) {
                  $uow->persist($notification) ; 
              }
              $entity->setNotification($notification) ; 
              $uow->persist($entity);
              $uow->computeChangeSets();
          }
        }
    }
}

问题仅在通知首次与实体关联时发生,即第一次在InventoryItem上设置到期日期。在更新到期日期的后续实例中,更新将在Notification和InventoryItem上正确反映。

任何想法或建议都将受到赞赏。

由于

2 个答案:

答案 0 :(得分:5)

您需要在新创建或更新的实体上专门调用computeChangeset 。仅调用computeChangeSets是不够的。

    $metaData = $em->getClassMetadata('Your\NameSpace\Entity\YourNotificationEntity');
    $uow->computeChangeSet($metaData, $notification);

答案 1 :(得分:2)

谢谢理查德。你指出了正确的方向。我需要重新计算父实体(InventoryItem)上的更改集以使事情正常工作。另外,我必须在工作单元上调用computeChangeSets以消除无效的参数编号错误(例如解释为symfony2 + doctrine: modify a child entity on `onFlush`: "Invalid parameter number: number of bound variables does not match number of tokens"的那个)

注意我最终还删除了:

if ( $notification ) {
    $uow->persist($notification) ; 
}

这从来没有意义,因为我已经在我的实体中设置了级联,并且应该自动级联。

我的最终解决方案是:

public function onFlush(OnFlushEventArgs $args)
{
    $em  = $args->getEntityManager();
    $uow = $em->getUnitOfWork();

    foreach ($uow->getScheduledEntityUpdates() as $entity) {
        if ($entity instanceof NotificableInterface) {
            if ($entity->generatesNotification()){
                $notification = $this->notificationManager->generateNotificationForEntity($entity) ;
                $entity->setNotification($notification) ; 
                // if ( $notification ) {
                //    $uow->persist($notification) ; 
                // }
                $metaData = $em->getClassMetadata(get_class($entity));
                $uow->recomputeSingleEntityChangeSet($metaData, $entity);
                $uow->computeChangeSets();
            }
        }
    }
}