2011-10-25 11 views
8

Estoy luchando con lo siguiente, en una clase de entidad tengo un preUpdate lifeCycleCallback que tiene que persistir una nueva entidad antes de que se vacíe los cambios para un auditTrail.Doctrine 2.1 Persist entidad en preUpdate lifeCycleCallback

En preRemove y prePersist esto funciona a la perfección pero en preUpdate no pasa nada. Si llamo a flush yo, va en un bucle recursivo.

De acuerdo con los grupos de Google para el usuario de doctrina, ponerlo en Flush debe ser una opción, pero en ese caso no puedo acceder a los valores anteriores de la entidad para guardar estos valores antiguos en otra entidad para el audittrail.

Algunos pequeño ejemplo de lo que estoy tratando de archivo:

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

No es verdadero código, sólo algo para ilustrar lo que quiero. También probé algo como esto:

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

que deberían funcionar de acuerdo a este tema: http://groups.google.com/group/doctrine-user/browse_thread/thread/bd9195f04857dcd4

Si llamo al ras de nuevo, pero que causa Apache se colapse debido a algún bucle infinito.

¿Alguien que tiene ideas para mí? ¡Gracias!

Respuesta

6

Nunca debe usar el entitymanager dentro de sus entidades. Si desea añadir pistas de auditoría, debe mapear la entidad "SomeEntity" a la entidad "AuditTrail" y hacer algo como

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

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

Si establece la opción de cascada en el mapeo, que conseguirá persistido cuando persistir "SomeEntity".

+0

¿Por qué no se debe utilizar el gestor de entidades dentro de mis entidades? Y si asigna el AuditEntity a SomeEntity, se asociará en la base de datos y no es lo que quiero copiar mis entidades y agregará otros campos como "acción" = actualizar, etc. Esta AuditEntity fue solo un ejemplo porque para auditar utilizo : https://github.com/keesschepers/EntityAudit –

+0

Usaría el eventmanager. Quería echarle un vistazo a tu código, pero aún no hay tiempo. – tvlooy

+1

Finalmente (¡hace un año!) Usé el gestor de eventos (EventSubscriber) para realizar estas tareas de forma global. He incluido esto en mi marco: https://github.com/php-pike/Pike (mira la parte de EntityAudit) ¡gracias! –

0

entitymanager-> persist() no funcionará dentro del método preUpdate. En lugar de eso, puede guardar los datos de AuditTrail en la sesión y después del enjuague de 'SomeEntity', tomar los datos de la sesión y ejecutar entitymanager-> persist (...) y entitymanager-> flush()

3

Tuve el mismo problema en el método preUpdate de un EventListener. Resolví esto almacenando la nueva entidad en una propiedad y moviendo las nuevas llamadas persist() y flush() al método 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(); 
} 

}

+0

Sé que parece un poco 'hackear' pero no puedo ver una solución 'oficial' para este caso de uso, también he usado este método –

+1

Desafortunadamente, llamar a 'flush()' dentro de una devolución de llamada del ciclo de vida no es compatible con Doctrine y esto no parece funcionar en versiones más nuevas de Doctrine; Me sale este error: http://www.doctrine-project.org/jira/browse/DDC-3218. –

+0

Consulte este enlace para saber cómo hacerlo correctamente: http://stackoverflow.com/questions/16904462/adding-additional-persist-calls-to-preupdate-call-in-symfony-2-1. Desearía que hubiera una forma de hacerlo dentro de la clase de entidad, en lugar de tener que crear una clase global separada ... –

Cuestiones relacionadas