symfony2更新eventListener中的相关实体

时间:2014-08-14 10:48:11

标签: php symfony doctrine-orm event-listener

我们有三个实体:

  1. MaterialAssigned
  2. 库存
  3. 工作
  4. MaterialAssigned包含三个字段:

    1. 数量(int)
    2. Job实体的关系
    3. Stock实体的关系
    4. 我们尝试在MaterialAssigned上写一个preUpdate(),其中包含新旧Quantity值,进行一些计算并更新相关Stock实体中的总总数量。 当我们在逻辑中var_dump()值时,一切似乎都按预期工作,但相关的Stock实体永远不会更新。

      这是EventListener的相关代码:

      public function preUpdate(PreUpdateEventArgs $eventArgs)
      {
          $entity = $eventArgs->getEntity();
           if ($entity instanceof MaterialAssigned) {
      
              $changeArray = $eventArgs->getEntityChangeSet();
              $pre_quantity = $changeArray['quantity'][0];
              $post_quantity = $changeArray['quantity'][1];
      
              // Here we call the function to do the calculation, for testing we just use a fixed value
              $entity->getStock()->setTotal(9999);
      
              $em   = $eventArgs->getEntityManager();
              $uow  = $em->getUnitOfWork();
              $meta = $em->getClassMetadata(get_class($entity));
              $uow->recomputeSingleEntityChangeSet($meta, $entity);
          }
      }
      

1 个答案:

答案 0 :(得分:1)

此处的问题是,preUpdate受到Doctrine限制,不允许在此方法中更新任何实体。另一方面,onFlush允许更新实体,并取代了对三种不同方法(更新,持久,删除)的需求。

然后我们找到了以下指南,提示解决方案:Tobias Sjösten's guide

我们的代码现在看起来像:

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

    // These collects an array of all the changes that are going to be flushed.
    // If you do not wish to see deleted entities just remove the line $uow->getScheduledEntityDeletions()
    $entities = array_merge(
        $uow->getScheduledEntityInsertions(),
        $uow->getScheduledEntityUpdates(),
        $uow->getScheduledEntityDeletions()
    );

    foreach ($entities as $entity) {

        if ($entity instanceof MaterialAssigned) {

            // This gets an array filled with the changes for the entire entity
            $changeArray = $uow->getEntityChangeSet($entity);

            $stock = $entity->getStock();

            // Here we call our function passing $changeArray.
            // This does some math and update the value. For simplicity we just
            // set the value manually in this example
            $stock->setTotal(9999);

            $md = $this->em->getClassMetadata('Northerncam\AppBundle\Entity\Stock');
            $uow->recomputeSingleEntityChangeSet($md, $stock);
        }
    }
}

这是print_r()的{​​{1}}:

$changeArray