Doctrine EventListener onFlush does not save original entity

核能气质少年 提交于 2019-12-25 04:43:17

问题


I've been struggling with an annoying issue for a while. I'm trying to create Notification entities associated to InventoryItems that expire.

These InventoryItems are generated automatically for users, but users can edit them and set expiry date on them individually. Upon saving, if an InventoryItem has an expiry date, a Notification entity is generated and associated to it. So these Notification entities are created when an entity is updated and hence onPersist event is not going to work.

Everything seems to work fine and Notifications are generated upon saving InventoryItems as expected. Only problem is, when a Notification is created for the first time, even though it's saved properly, changes to the InventoryItem are not saved. That is a Notification with correct expiry date is created, but the expiry date is not saved on the InventoryItem.

Here's my onFlush code:

 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();
          }
        }
    }
}

The problem only occurs the first time a Notification is associated to an entity, i.e. the first time an expiry date is set on an InventoryItem. In later instances when expiry date is updated, the update is reflected correctly on both the Notification and InventoryItem.

Any ideas or suggestions would be appreciated.

Thanks


回答1:


You need to call computeChangeset specifically on your newly created or updated entity. Just calling computeChangeSets is not enough.

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



回答2:


Thanks Richard. You pointed me to the right direction. I needed to recompute the change set on the parent entity (InventoryItem) to get things working properly. Additionally I had to call computeChangeSets on the unit of work to get rid of the invalid parameter number error (such as the one explained symfony2 + doctrine: modify a child entity on `onFlush`: "Invalid parameter number: number of bound variables does not match number of tokens")

Note I ended up also removing:

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

Which never made sense, since I had set cascade persist on the association in my entity and should have cascaded down automatically.

My final solution is:

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();
            }
        }
    }
}


来源:https://stackoverflow.com/questions/34342324/doctrine-eventlistener-onflush-does-not-save-original-entity

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!