Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Doctrine 2.1 Persist entity in preUpdate lifeCycleCallback

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!

like image 867
Kees Schepers Avatar asked Oct 25 '11 10:10

Kees Schepers


2 Answers

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".

like image 98
tvlooy Avatar answered Sep 25 '22 17:09

tvlooy


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

}

like image 33
ACNB Avatar answered Sep 25 '22 17:09

ACNB