postPersist事件不更新数据库

时间:2014-08-26 12:07:35

标签: symfony doctrine-orm persistence listener

我有2个实体,Invoice和Advance。进展与发票有关,与ManyToOne有关。在添加,编辑和推进时,我希望相应地编辑发票总额。我为Advances postPersist设置了一个听众,如下所示:

class PostPersistListener
{
    protected $container;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
    }

    public function postPersist(LifecycleEventArgs $args)
    {
        $entity = $args->getEntity();
        $em = $args->getEntityManager();

        // Advance Listener
        if ($entity instanceof Advance) {

            // Modification du total de la facture mère
            $invoice = $entity->getInvoice();

            echo '<pre>';
            \Doctrine\Common\Util\Debug::dump($invoice);
            echo '</pre>';

            $newTotal = $invoice->getTotalMaster() - $entity->getTotalMaster();
            $invoice->setTotalMaster($newTotal);

            echo '<pre>';
            \Doctrine\Common\Util\Debug::dump($invoice);
            echo '</pre>';

            $em->flush();

        }

    }
}

事件被很好地触发了。第一个dump()显示如下:

object(stdClass)#1379 (49) {
  ["__CLASS__"]=>
  string(32) "Evo\BackendBundle\Entity\Invoice"
  ["id"]=>
  int(1)
  ["totalMaster"]=>
  float(250)
}

第二次转储():

object(stdClass)#1379 (49) {
  ["__CLASS__"]=>
  string(32) "Evo\BackendBundle\Entity\Invoice"
  ["id"]=>
  int(1)
  ["totalMaster"]=>
  float(240)
}

所以&#34; totalMaster&#34;财产被修改。但$ em-&gt; flush()似乎并没有更新数据库中的字段。我错过了什么吗?

2 个答案:

答案 0 :(得分:3)

首先,正如其名称所暗示的那样,PostPersist仅在初始持续操作之后触发,即仅针对新对象。编辑现有对象不会触发事件。

来自:http://docs.doctrine-project.org/en/latest/reference/events.html#lifecycle-events

postPersist - The postPersist event occurs for an entity after the entity has been made persistent. 
It will be invoked after the database **insert** operations. 
Generated primary key values are available in the postPersist event.

对这些事件的处理也有严格的限制。基本上,刷新操作已经在进行中,因此更新实体的任何事情都充其量是有问题的。具体做法是:

来自:http://docs.doctrine-project.org/en/latest/reference/events.html#postupdate-postremove-postpersist

The three post events are called inside EntityManager#flush(). 
Changes in here are not relevant to the persistence in the database, 
but you can use these events to alter non-persistable items, like non-mapped fields, logging or 
even associated classes that are directly mapped by Doctrine.

你几乎不可能使用prePersist和preUpdate来解决这个问题,但这些问题有其自身的问题。

@kix有正确的方法。更新发票总额是域功能,应使用域事件处理。

P.S。您不需要对通过Doctrine检索的现有对象调用persist。

答案 1 :(得分:0)

您错过了$em->persist($invoice)行。

另外,我建议使用Symfony的内置事件来实现这个逻辑,而不是prePersist个侦听器。这背后的简单原因是您的代码处理业务逻辑而不是持久性逻辑。您应该使用AdvanceModified服务(它应该可供您的控制器使用)发送event_dispatcher事件,然后在监听器中处理它。