2011-10-11 18 views
6

Estoy usando las entidades de Doctrine 2. Tenemos algunas entidades que tienen que actualizar los elementos relacionados cuando se guardan en la base de datos. Por ejemplo, cuando se modifica un registro de usuario, lo guardamos como un nuevo registro, con el campo "inactivo" establecido en 'falso'. Sin embargo, tenemos que establecer el campo "inactivo" para todos los registros anteriores para ese usuario en "verdadero". Esto se hace para mantener un historial de auditoría. Es una base de datos heredada, por lo que cambiar la estructura no es una opción.Doctrine 2, Necesito ejecutar el código pre-persist/post-persist

Dado que Doctrine guarda objetos pasándolos a un objeto persistido (persist :: ($ thisObj)), en lugar de que el objeto tenga un método guardar ($thisObj->save()), no podemos extender un método 'guardar' desde objeto primario La única opción que veo aquí es tratar de extender el objeto "persistir", pero eso suena como una manada de ganso, esperando a suceder.

Encontré algo de información sobre eventos, pero no veo cómo agregarlos para hacer que los eventos activen una función en particular cuando persiste una entidad en particular.

¿Cómo agrego la funcionalidad de guardado previo/posterior a algunas de mis entidades?

Respuesta

12

Entonces, probablemente ya sepa http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html ¿verdad?

Agregue una anotación que la entidad contiene devoluciones de llamada y luego cree funciones específicas (que deben ser públicas) en esa entidad y también anótelas con @PrePersist o @PostPersist o lo que sea.

La otra forma es crear un suscriptor de evento, registrarlo con el administrador de eventos de doctrina e implementar métodos llamados prePersist, postPersist, etc. Se pasa un objeto EventArguments que contiene la entidad relevante para el evento ocurrido.

Sé que esta es una respuesta muy general a su pregunta, pero debe ser un poco más específico donde se encuentra su problema.

Por favor, no ejecute el administrador de entidades y sobrescriba el método de persistencia, hay métodos más limpios para hacer lo que necesita hasta donde yo sé.

7

En realidad, es bastante simple hacer lo que quiere hacer. No requiere dorking con el gestor de eventos ni nada complejo como eso. Utiliza algo llamado "devoluciones de llamada de ciclo de vida". Estas son funciones que Doctrine ejecuta automáticamente durante el "ciclo de vida" de la entidad, es decir: prePersist, postPersist, preUpdate, postUpdate, etc. Puede encontrar la lista completa aquí: http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html

El proceso de agregar esta funcionalidad a sus entidades es muy simple.

  1. En la sección Anotaciones de su entidad, incluya la siguiente etiqueta: "@HasLifecycleCallbacks". Esto le dice a Doctrine que debe buscar en la entidad las funciones que se ejecutarán en varios eventos
  2. Escriba una función pública en su entidad que desee activar en un evento específico.
  3. Ponga una anotación sobre la función que indica qué evento se debe utilizar para manejar.

Por ejemplo, mira el siguiente código:

/** @PostPersist */ 
public function doSPostPersist() { 
    $this->tester = 'Value changed by post-persist'; 
} 

he encontrado que a veces los acontecimientos simplemente se niegan a disparar, y yo todavía no sé qué.Pero cuando disparan, dispararán de manera confiable.

+2

bien, descubierto por qué los acontecimientos a veces "simplemente se niegan a disparar". Los eventos prePersist/posPersist ocurren solo cuando se guarda un nuevo registro. Si está actualizando un registro existente, el preUPdate/postUpdate unifica el fuego en su lugar. Por lo tanto, aunque llame al método persist, si está guardando un objeto existente, se aplicarán los eventos de ciclo de vida preUpdate/postUpdate. –

+0

Gracias por guiarme en la dirección correcta. Un seguimiento: Inherto todas mis entidades de una clase base para darle algunas características generales. Odio tener que poner un evento en cada entidad, porque en mi caso realmente uso postload para disparar el constructor, y quiero esto en todas las entidades. ¿Hay alguna manera de mover esto a la clase base sin tener que hacer mucho más copiar y pegar en la entidad? – redreinard

+0

¡El segundo punto fue muy útil para mí! ¡Muchas gracias! –

2

No se olvide de permitir que las devoluciones de llamada de ciclo de vida en su clase de anotación:

/** 
* Report\MainBundle\Entity\Serveur 
* @ORM\HasLifecycleCallbacks 
*/ 
class Serveur { 
+0

¿Es necesaria la parte "ORM \"? Parece que funciona bien para mí sin eso, pero quiero ir con las mejores prácticas. – redreinard

+0

esa no es una mejor práctica, es solo un alias para el administrador de asignación use Doctrine \ ORM \ Mapping como ORM; ... /** * @ORM \ HasLifecycleCallbacks * / – ROLO