2011-10-11 12 views
6

Używam obiektów Doctrine 2. Mamy pewne podmioty, które muszą aktualizować powiązane elementy, gdy są zapisane w bazie danych. Na przykład, gdy rekord użytkownika zostanie zmodyfikowany, zapisujemy go jako nowy rekord, a pole "nieaktywne" jest ustawione na "fałsz". Musimy jednak ustawić pole "nieaktywne" dla wszystkich poprzednich rekordów dla tego użytkownika na "true". Ma to na celu utrzymanie historii audytu. Jest to baza danych Legacy, więc zmiana struktury nie jest opcją.Doctrine 2, Konieczność wykonania kodu pre-persist/post-persist

Ponieważ Doctrine zapisuje obiekty, przekazując je do obiektu trwałego (persist :: ($ thisObj)), a nie do obiektu posiadającego metodę zapisu ($thisObj->save()), nie możemy po prostu rozszerzyć metody "zapisywania" z obiekt nadrzędny. Jedyną opcją, którą tu widzę, jest próba przedłużenia obiektu "upartego", ale brzmi to jak gęsie gęsi, tylko czekając, aby się wydarzyć.

Znalazłem trochę informacji o zdarzeniach, ale nie widzę sposobu ich dodania, aby zdarzenia wywoływały określoną funkcję, gdy dany obiekt byłby utrwalony.

Jak dodać funkcję zapisywania/zapisywania po zamknięciu do niektórych moich obiektów?

Odpowiedz

12

Więc, prawdopodobnie już wiesz, http://www.doctrine-project.org/docs/orm/2.1/en/reference/events.html prawda?

Dodajesz adnotację, że encja zawiera wywołania zwrotne, a następnie tworzy określone funkcje (które muszą być publiczne) na tym elemencie, a także adnotuje je za pomocą @PrePersist lub @PostPersist lub cokolwiek innego.

Innym sposobem jest stworzenie subskrybenta zdarzenia, zarejestrowanie go za pomocą menedżera zdarzeń doktryny i wdrożenie metod o nazwie prePersist, postPersist itp. Otrzymują obiekt EventArguments zawierający encję istotną dla zdarzenia.

Wiem, że jest to bardzo ogólna odpowiedź na twoje pytanie, ale musisz być bardziej konkretny, gdzie leży twój problem.

Proszę nie wysyłać menedżera encji i nie nadpisywać metody persist, istnieją metody czystsze dla robienia tego, co jest potrzebne, o ile mogę powiedzieć.

7

To naprawdę proste, aby zrobić to, co chcesz robić. Nie wymaga dorkowania z menadżerem wydarzeń ani niczego tak skomplikowanego. Używasz czegoś zwanego "Oddzwanianiem cyklu życia". Są to funkcje, które automatycznie uruchamia Nauki podczas „cyklu życia” podmiotu, tj: prePersist, postPersist, preUpdate, postUpdate, itd. Można znaleźć pełną listę tutaj: http://www.doctrine-project.org/docs/orm/2.0/en/reference/events.html

proces dodawania tej funkcji do podmiotów jest bardzo prosty.

  1. W sekcji Adnotacje twojego podmiotu umieść następujący tag: "@HasLifecycleCallbacks". To mówi Doctrine, że powinien przeszukiwać encję, aby funkcje działały podczas różnych zdarzeń.
  2. Napisz funkcję publiczną w twojej istocie, którą chciałbyś strzelić w określonym wydarzeniu.
  3. Umieść adnotację powyżej funkcji wskazującej, które zdarzenie będzie używane do obsługi.

Na przykład, spójrz na następujący kod:

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

I odkryli, że czasami po prostu odmówić zdarzenia na ogień, a ja jeszcze nie wiem dlaczego.Ale kiedy wystrzelą, wystrzelą niezawodnie.

+2

OK, zorientowali się, dlaczego czasami wydarzenia „po prostu odmówić ognia”. Zdarzenia prePersist/posPersist występują tylko podczas zapisywania nowego rekordu. Jeśli aktualizujesz istniejący rekord, preUPdate/postUpdate wyrównuje ogień. Tak więc mimo wywołania metody persist, jeśli zapisujesz istniejący obiekt, mają zastosowanie zdarzenia cyklu przed aktualizacją/postUpdate. –

+0

Dzięki za prowadzenie we właściwym kierunku. Jedna obserwacja: dziedziczy wszystkie moje jednostki z klasy bazowej, aby nadać jej pewne ogólne cechy. Nienawidzę umieszczać zdarzenia w każdym obiekcie, ponieważ w moim przypadku po prostu używam postLoad do odpalenia konstruktora, a ja chcę to na wszystkich elementach. Jakikolwiek sposób przeniesienia tego do klasy bazowej bez konieczności wykonywania dodatkowej kopii i wklejania w obiekcie? – redreinard

+0

Drugi punkt był dla mnie bardzo przydatny! Dziękuję Ci bardzo! –

2

Nie zapomnij włączyć Lifecycle oddzwaniania w swojej klasie adnotacji:

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

Czy potrzebna jest część "ORM \"? Wydaje się, że działa bez niego dobrze, ale chcę iść z najlepszą praktyką. – redreinard

+0

To nie jest najlepsza praktyka, to po prostu alias dla menedżera mapowania użyj Doctrine \ ORM \ Mapping jako ORM; ... /** * @ORM \ HasLifecycleCallbacks * / – ROLO