2011-10-11 3 views
6

Sto usando le entità Doctrine 2. Abbiamo alcune entità che devono aggiornare gli elementi correlati quando vengono salvati nel database. Ad esempio, quando un record utente viene modificato, lo salviamo come nuovo record, con il campo "inattivo" impostato su "falso". Tuttavia, dobbiamo impostare il campo 'inattivo' per tutti i record precedenti per quell'utente su 'true'. Questo è fatto per mantenere una cronologia di controllo. È un database Legacy, quindi cambiare la struttura non è un'opzione.Doctrine 2, Necessario eseguire codice pre-persist/post-persist

Dal momento che Doctrine salva gli oggetti passandoli su un oggetto persistente (persist :: ($ thisObj)), piuttosto che l'oggetto con un metodo di salvataggio ($thisObj->save()), non possiamo semplicemente estendere un metodo 'salva' da un oggetto genitore. L'unica opzione che vedo qui è cercare di estendere l'oggetto "persist", ma suona come un goose gaggle, che aspetta solo di succedere.

Ho trovato alcune informazioni sugli eventi, ma non vedo come aggiungerli per far sì che gli eventi attivino una funzione particolare quando una particolare entità viene mantenuta.

Come aggiungere funzionalità pre-salvataggio/post-salvataggio ad alcune delle mie entità?

risposta

12

Quindi probabilmente conosci già http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html?

Si aggiunge un'annotazione che l'entità contiene richiamate e quindi crea funzioni specifiche (che devono essere pubbliche) su quell'entità e le annota anche con @PrePersist o @PostPersist o qualsiasi altra cosa.

L'altro modo è la creazione di un abbonato evento, registrare quello con il gestore dell'evento dottrina e implementare metodi chiamati prePersist, PostPersist ecc Essi viene passato un EventArguments oggetto che contiene l'entità rilevante per l'evento verificatosi.

So che questa è una risposta molto generale alla tua domanda, ma devi essere un po 'più specifico in cui si trova il tuo problema.

Si prega di non chiudere il gestore di entità e sovrascrivere il metodo persist, ci sono metodi più puliti per fare ciò che è necessario per quanto posso dire.

7

In realtà è piuttosto semplice fare ciò che si vuole fare. Non richiede dorking con il gestore eventi o qualcosa di così complesso. Si utilizza qualcosa chiamato "callback del ciclo di vita". Queste sono le funzioni che Doctrine esegue automaticamente durante il "ciclo di vita" dell'entità, ovvero: prePersist, postPersist, preUpdate, postUpdate, ecc. Puoi trovare l'elenco completo qui: http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html

Il processo di aggiunta di questa funzionalità alle tue entità è molto semplice

  1. Nella sezione Annotazioni dell'entità, includere il tag seguente: "@HasLifecycleCallbacks". Questo dice a Doctrine che dovrebbe cercare nell'entità le funzioni da eseguire su vari eventi
  2. Scrivere una funzione pubblica nella propria entità che si desidera attivare su un evento specifico.
  3. Inserire un'annotazione sopra la funzione che indica quale evento deve essere utilizzato per gestire.

Per esempio, guardo il seguente codice:

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

Ho scoperto che a volte gli eventi semplicemente si rifiutano di sparare, e io non so ancora perché.Ma quando fanno fuoco, sparano in modo affidabile.

+2

OK, capito il motivo per cui a volte gli eventi "semplicemente si rifiutano di sparare". Gli eventi prePersist/posPersist si verificano solo quando si salva un nuovo record. Se si sta aggiornando un record esistente, si attiva invece il comando preUPdate/postUpdate. Pertanto, anche se si chiama il metodo persist, se si sta salvando un oggetto esistente, si applicano gli eventi del ciclo di vita preUpdate/postUpdate. –

+0

Grazie per avermi guidato nella giusta direzione. Un follow-up: eredito tutte le mie entità da una classe base per dargli alcune caratteristiche generali. Odio dover mettere un evento in ogni entità, perché nel mio caso uso davvero postLoad per attivare il costruttore, e voglio questo su tutte le entità. Un modo per spostare questo nella classe base senza dover fare molto copia e incolla in più nell'entità? – redreinard

+0

Il secondo punto è stato molto utile per me! Grazie mille! –

2

Non dimenticare di abilitare Lifecycle richiamate nella vostra annotazione classe:

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

La parte "ORM \" è necessaria? Sembra che funzioni senza di me, ma voglio andare con le migliori pratiche. – redreinard

+0

non è una best practice, è solo un alias per il gestore mappe utilizza Doctrine \ ORM \ Mapping come ORM; ... /** * @ORM \ HasLifecycleCallbacks * / – ROLO