Doctrine 2.1 Persist entity in preUpdate lifeCycle

2019-04-24 09:36发布

I'm struggling with the following, in a entity class I have a preUpdate lifeCycleCallback which has to persist a new entity before it flushes the changes for a auditTrail.

In preRemove and prePersist this works perfectly but in preUpdate nothing happends. If I call flush myself it goes in a recursive loop.

According to the Google groups for doctrine-user putting it in onFlush should be a option but in that event I can't access the old values of the entity to save this old values in a new other entity for the audittrail.

Some small example what i'm trying to archive:

<?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 :-(
    }
}
?>

It's not real code, just something to illustrate you what I want. I also tried something like this:

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

Which should work according to this topic: http://groups.google.com/group/doctrine-user/browse_thread/thread/bd9195f04857dcd4

If I call the flush again but that causes Apache to crash because of some infinite loop.

Anyone who got ideas for me? Thanks!

3条回答
叛逆
2楼-- · 2019-04-24 10:22

You should never use the entitymanager inside your entities. If you would like to add audit trails, you should map the "SomeEntity" entity to the "AuditTrail" entity and do something like

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

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

If you set the cascade option on the mapping, it will get persisted when you persist "SomeEntity".

查看更多
Anthone
3楼-- · 2019-04-24 10:25

entitymanager->persist() will not work inside the preUpdate method. Instead of that, you can save the AuditTrail data to session and after the flush of the 'SomeEntity', take the data from session and perform entitymanager->persist(...) and entitymanager->flush()

查看更多
太酷不给撩
4楼-- · 2019-04-24 10:33

I had the same problem in the preUpdate method of an EventListener. I solved this by storing the new entity in a property and moving the new persist() and flush() calls to the postUpdate method.

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

}

查看更多
登录 后发表回答