2012-07-06 6 views
10

que detecta este problema "gracias" a una excepción que tengo:Symfony 2 - ras en PostUpdate caso PreUpdate fuego

Catchable Fatal Error: Argument 3 passed to 
Doctrine\ORM\Event\PreUpdateEventArgs::__construct() 
must be an array, null given, called in 
/.../vendor/doctrine/lib/Doctrine/ORM/UnitOfWork.php on line 804 
and defined in 
/.../vendor/doctrine/lib/Doctrine/ORM/Event/PreUpdateEventArgs.php line 28 

estoy trabajando en un proyecto que requieres una lógica específica:
Cuando el campo order en la entidad book se modifica, necesito actualizar el campo books_order_modified_at en la entidad matriz bookstore (este campo me permite saber si se modificó el orden de los libros en una librería).

Decidí hacerlo en un detector de eventos ya que hay muchos lugares en el código que pueden cambiar el orden de los libros.

no he encontrado ninguna manera de actualizar una entidad relacionada de preUpdate evento, así que tengo un campo privado en la clase oyente que utilizo para contar el evento postUpdate para actualizar la entidad correspondiente bookstore.

Mi problema es que cuando lo hago, el evento preUpdate de la entidad book se activa.
Cuando reviso el conjunto de cambios, solo contiene el campo modified_at, pero tiene el mismo valor antes y después.

Si alguien tiene otra idea de cómo resolver el problema, genial.

Si no, ¿alguna idea de cómo puedo evitar que se active el evento preUpdate cuando se llama el color en el evento postUpdate ??

+0

¿Encontró una solución para este problema? – ownking

+0

No, en realidad resolví mi problema usando el servidor en tiempo real (node.js), por lo que ya no busco una solución para esto. Sin embargo, si tiene alguno, será interesante verlo. ¡Gracias! – guyaloni

Respuesta

1

¿Qué hay de la actualización de modified_at en sus entidades y dejar que doctrine lo resuelva? Se podría cambiar la forma de setOrder en su libro para actualizar la entidad BookOrder así:

class Book { 
    public function setOrder($order) { 
     // modify book 
     $this->bookOrder->updateModifiedAt(); 
    } 
} 

Por supuesto, su BookOrder tendría que implementar modifiedAt:

class BookOrder { 
    public function updateModifiedAt() { 
     $this->modifiedAt = new \DateTime(); 
    } 
} 

Si utiliza otras clases de la fecha y hora, ¡por supuesto tienes que cambiar este código!

Doctrine debe reconocer que BookOrder ha cambiado y debe actualizarlo sin necesidad de utilizar un detector de eventos.

0

Puedo sugerirle que use la extensión Timestampable para Doctrine desde DoctrineExtensionsBundle.

Al usarlo no es necesario configurar created_at o modified_at valores. Esta extensión lo hace automáticamente. Incluso puede establecer modified_at solo cuando se hayan modificado campos específicos. Ver example.

Creo que está escribiendo algo así como esta extensión. Por lo tanto, no necesita hacer eso porque esto ya está hecho :)

+1

Mi problema es que el campo timestampable que quiero actualizar es de otra entidad, no de la entidad que se modifica. Es una buena extensión, pero creo que en mi caso no resolverá el problema. – guyaloni

6

En realidad, este es un problema de la doctrina Doctrine Issue DDC-2726. Lo resolvió agregando una llamada clara al administrador de entidades después de la descarga en el oyente, de modo que el tercer argumento de ese constructor, que en realidad es la entidad Cambios de configuración, se volverá a escribir.

+1

¿Cómo se realiza una "llamada clara al administrador de la entidad? ¿Puedes describirlo? – tomazahlin

+2

" $ args-> getEntityManager() -> borrar(); "Simplemente llamando al método claro del administrador de la entidad. –

+0

Gracias, Necesito investigar esto, para comprender realmente lo que está pasando. – tomazahlin

0

Tuve un problema similar a esto. Intentar usar preupdate para modificar elementos secundarios causó el mismo error.Al final, mi solución es simplemente actualizar a los niños que pertenecen al padre. No se requiere una llamada explícita al flush.

/** 
* Update expiry dates for all runners belonging to a campaign 
* 
* @param $runners 
* @param $expiryDate 
*/ 
private function updateCampaignRunners($runners, $expiryDate){ 
    foreach($runners as $runner){ 
     $runner->setExpiresAt($expiryDate); 
     $this->getModelManager()->update($runner); 
    } 
} 

/** 
* Post update and persist lifecycle callback 
* 
* @param Campaign $campaign 
*/ 
private function postAction(Campaign $campaign) 
{ 
    $runnerExpire = $this->getForm()->get("runnerExpire")->getData(); 
    if($runnerExpiryDate && $campaign->getRunners()){ 
     $this->updateCampaignRunners($campaign->getRunners(), $runnersExpiryDate); 
    } 
}