Doctrine 2.1在preUpdate lifeCycleCallback中持久化实体

时间:2011-10-25 10:07:41

标签: orm doctrine-orm

我正在努力解决以下问题,在实体类中我有一个preUpdate lifeCycleCallback,它必须在刷新auditTrail的更改之前保留一个新实体。

在preRemove和prePersist中,这可以很好地工作,但在preUpdate中没有任何事情发生。如果我自己调用flush,它会进入递归循环。

根据教学用户的Google群组,将其放入onFlush应该是一个选项,但在这种情况下,我无法访问实体的旧值,以将此旧值保存在audittrail的新其他实体中。 / p>

我想要存档的一些小例子:

<?php
/**
 * @Entity
 * @HasLifeCycleCallbacks
 */
class someEntity {
    ... annotations ...


    /**
     * @PreUpdate
     */
    public function addAuditTrail() {
        $em = \Zend_Registry::get('doctrine')->getEntityManager();

        $entity = new AuditTrail();
        $entity->action = 'update';
        $entity->someField = $this->someField;

        $em->persist($entity); //this just doesn't do anything :-(
    }
}
?>

这不是真正的代码,只是为了说明你想要的东西。我也试过这样的事情:

$em->getUnitOfWork()->computeChangeSet($em->getClassMetaData(get_class($entity)), $entity);

根据此主题应该有效:http://groups.google.com/group/doctrine-user/browse_thread/thread/bd9195f04857dcd4

如果我再次调用flush,但由于某些无限循环而导致Apache崩溃。

任何有想法的人?谢谢!

3 个答案:

答案 0 :(得分:6)

您绝不应在实体内使用entitymanager。如果您想添加审计跟踪,您应该将“SomeEntity”实体映射到“AuditTrail”实体并执行类似

的操作
/**
 * @PreUpdate
 */
public function addAuditTrail() {
    $entity = new AuditTrail();
    $entity->action = 'update';
    $entity->someField = $this->someField;

    $this->autitTrail->add($entity);
}

如果在映射上设置了级联选项,则在持久保存“SomeEntity”时它将保持不变。

答案 1 :(得分:3)

我在EventListener的preUpdate方法中遇到了同样的问题。我通过将新实体存储在属性中并将新的persist()和flush()调用移动到postUpdate方法来解决这个问题。

class someEntity {
... annotations ...

protected $store;

/**
 * @PreUpdate
 */
public function addAuditTrail() {
    //$em = \Zend_Registry::get('doctrine')->getEntityManager();

    $entity = new AuditTrail();
    $entity->action = 'update';
    $entity->someField = $this->someField;

    // replaces $em->persist($entity); 
    $this->store = $entity;
}

/**
 * @PostUpdate
 */
public function saveAuditTrail() {
    $em = \Zend_Registry::get('doctrine')->getEntityManager();
    $em->persist($this->store); 
    $em->flush();
}

}

答案 2 :(得分:0)

entitymanager-&gt; persist()在preUpdate方法中不起作用。 除此之外,您可以将AuditTrail数据保存到会话中,并在刷新“SomeEntity”之后,从会话中获取数据并执行entitymanager-&gt; persist(...)和entitymanager-&gt; flush()