2012-07-06 7 views
10

Ho rilevato questo problema "grazie" ad un'eccezione che ho ottenuto:Symfony 2 - a filo in postUpdate evento fuoco PreUpdate

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 

Sto lavorando su un progetto che requieres una logica specifica:
Quando il campo order nell'entità book viene modificato, devo aggiornare il campo books_order_modified_at nell'entità padre bookstore (questo campo mi consente di sapere se l'ordine dei libri in una libreria è stato modificato).

Ho deciso di farlo in un listener di eventi poiché ci sono molti punti nel codice che potrebbero cambiare l'ordine dei libri.

non ho trovato alcun modo per aggiornare un'entità correlata da preUpdate evento, quindi ho un campo privato della classe ascoltatore che io uso per raccontare l'evento postUpdate per aggiornare il relativo bookstore entità.

Il mio problema è che quando si esegue l'evento preUpdate dell'entità book viene generato.
Quando controllo il set di modifiche, contiene solo il campo modified_at, ma ha lo stesso valore prima e dopo.

Se qualcuno ha un'altra idea di come risolvere il problema - ottimo.

In caso negativo - qualsiasi idea in che modo è possibile impedire l'attivazione dell'evento preUpdate quando viene chiamato il flush nell'evento postUpdate ??

+0

Avete trovato una soluzione per questo problema? – ownking

+0

No, in realtà ho risolto il problema utilizzando il server in tempo reale (node.js), quindi non sono più alla ricerca di una soluzione. Tuttavia, se ne hai, sarà interessante vederlo. Grazie! – guyaloni

risposta

1

Che dire dell'aggiornamento dello modified_at all'interno delle entità e lasciare che doctrine lo gestisca? Si potrebbe cambiare il metodo setOrder nel tuo libro per aggiornare l'entità BookOrder in questo modo:

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

Naturalmente il vostro BookOrder avrebbe dovuto implementare modifiedAt:

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

Se si utilizzano altre classi per il vostro Datetime, ovviamente devi cambiare questo codice!

Doctrine dovrebbe riconoscere che BookOrder è stato modificato e deve aggiornarlo senza necessità di utilizzare un listener di eventi.

0

Posso suggerire di utilizzare l'estensione Timestampable per Doctrine da DoctrineExtensionsBundle.

Usandolo non è necessario impostare i valori created_at o modified_at. Questa estensione lo fa automaticamente. Anche se è possibile impostare modified_at solo quando sono stati modificati campi specifici. Vedi example.

Penso che tu stia scrivendo qualcosa come questa estensione. Quindi, non è necessario farlo perché questo è già fatto :)

+1

Il mio problema è che il campo del timestamp che voglio aggiornare è di un'altra entità, non dell'entità che viene modificata. È una bella estensione, ma penso che nel mio caso non risolverà il problema. – guyaloni

6

In realtà, questo è un problema dalla dottrina Doctrine Issue DDC-2726. Risolto aggiungendo una chiamata chiara sul gestore di entità dopo lo svuotamento nel listener in modo che l'argomento 3-rd di quel costruttore, che in realtà è entityChangeSets, verrà riscritto.

+1

Come si fa una "chiamata chiara sul gestore di entità, puoi descriverlo? Grazie! – tomazahlin

+2

" $ args-> getEntityManager() -> clear(); "Semplicemente chiamando il metodo clear del gestore entità. –

+0

Grazie, Ho bisogno di esaminare questo, per capire veramente cosa sta succedendo – tomazahlin

0

Ho avuto un problema simile a questo. Cercando di utilizzare preupdate per modificare elementi figlio ha causato lo stesso errore.Alla fine, la mia soluzione per aggiornare semplicemente i bambini appartenenti al genitore. Nessuna chiamata esplicita a flush richiesta.

/** 
* 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); 
    } 
}