![]() |
![]() |
![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 206 Pomógł: 4 Dołączył: 2.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Ostatnio pisząc jakiś kod w symfony2 potrzebowałem wykonać następujące czynności związane z aktualizacją pola ordering.
Znużmy, że mam table (Entity), która ma pole ordering. Chciałbym w tym Entity zrobić metody, które obsługiwałby aktualizację orderingów po takich czynnościach jak usunięcie, dodanie nowego, zmiana istniejącego. Niestety w Entity nie mam dostępu do EntityManagera. Nie mogłem go też wstrzyknąć. Jak realizujecie tego typu problemy? Czy wykonywanie zapytań z modelu jest dobrą praktyką? Może należałoby stworzyć Event, który realizowałby tego typu funkcjonalności. |
|
|
![]() |
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 2 291 Pomógł: 156 Dołączył: 23.09.2007 Skąd: ITALY-MILAN Ostrzeżenie: (10%) ![]() ![]() |
Jest cos takiego jak Callbacks mniej wiecej dziala to jak eventy ale jest latwiejsze w implementacji, znawca nie jestem bo sam sie ucze symfony2.
http://docs.doctrine-project.org/projects/...cycle-callbacks -------------------- Zainteresowania: XML | PHP | MY(SQL)| C# for .NET | PYTHON
http://code.google.com/p/form-builider/ Moj blog |
|
|
![]()
Post
#3
|
|
Grupa: Zarejestrowani Postów: 26 Pomógł: 4 Dołączył: 14.05.2010 Ostrzeżenie: (0%) ![]() ![]() |
W tym przypadku callback niewiele pomoże, bo wymagana jest edycja innych wpisów w bazie niż ten jeden.
Moim zdaniem jest to zły pomysł, aby w Entity mieszać cokolwiek związanego z bazą. Masz dwa rozwiązania: - dodać event i na jego podstawie aktualizować zawartość bazy - zdecydować się na coś gotowego: m.in. stof doctrine extensions(http://knpbundles.com/stof/StofDoctrineExtensionsBundle) lub phpcr (http://knpbundles.com/doctrine/DoctrinePHPCRBundle) Być może jest coś jeszcze, ale ja używam od jakiegoś czasu Stof i działa, więc się tym dłużej nie interesowałem. Ten post edytował misi3kk 15.09.2012, 15:40:29 -------------------- Accesto.pl
|
|
|
![]()
Post
#4
|
|
![]() Grupa: Zarejestrowani Postów: 206 Pomógł: 4 Dołączył: 2.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Zgadza się callbacks to podstawa do dalszego działania. Za pomocą callback mogę zmienić zawartość poszczególnego Entity, ale nie mogę zmienić innego. Nie mogę zrobić postDelete, który odejmie -1 dla wszystkich Enetity, które mają ordering większy od orderingu Entity, które było usunięte.
Właśnie w tym tkwi mój problem. W tym przypadku callback niewiele pomoże, bo wymagana jest edycja innych wpisów w bazie niż ten jeden. Moim zdaniem jest to zły pomysł, aby w Entity mieszać cokolwiek związanego z bazą. Masz dwa rozwiązania: - dodać event i na jego podstawie aktualizować zawartość bazy - zdecydować się na coś gotowego: m.in. stof doctrine extensions(http://knpbundles.com/stof/StofDoctrineExtensionsBundle) lub phpcr (http://knpbundles.com/doctrine/DoctrinePHPCRBundle) Być może jest coś jeszcze, ale ja używam od jakiegoś czasu Stof i działa, więc się tym dłużej nie interesowałem. Używałem pluginu, o którym piszesz ale trochę w innych celach. Czy mógłbys napisać jak konkretnie rozwiązać mój problem za pomocą tego bundla? W przypadku eventów, trochę boję się ich używać do tego typu rozwiązań z prostego powodu. Trudniej się utrzymuje, debuguje aplikacje opartą o architekturę eventów. Zwłaszcza jeśli wpływa on na dane w bazie. |
|
|
![]()
Post
#5
|
|
Grupa: Zarejestrowani Postów: 26 Pomógł: 4 Dołączył: 14.05.2010 Ostrzeżenie: (0%) ![]() ![]() |
Nie jestem pewien, ale pierwszy z podanych bundle (stof) pozwala chyba na użycie wszystkich gedmo doctrine extensions.
Do tej poru używałem głównie tree, ale za prawdopodobnie nie potrzebujesz aż tak rozbudowanej funkcjonalności (można zablokować na jeden root). http://www.gediminasm.org/article/sortable...n-for-doctrine2 Sortable powinien działać - nie robi on nic więcej niż listener+repo z paroma dodatkowymi funkcjami, więc możesz albo użyć tego gotowego, albo napisać to samemu. Wydaje mi się, że inaczej niż na eventach zrobić się tego nie da. Podawanie EM do Entity może okazać się niebezpieczne. Ostatecznie zawsze możesz zrobić to po stronie bazy danych. -------------------- Accesto.pl
|
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 206 Pomógł: 4 Dołączył: 2.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Problem jest bardziej obszerny. Problem sortowania dałem jako przykład, ale chodzi o idee. Czyli jak aktualizować jakieś dane z callback modelu dotyczące innej tabeli niż tej, na której dokonywane są operacje.
|
|
|
![]()
Post
#7
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Takie zadanie nie powinno być w ogóle wykonywane na poziomie encji. Od tego jest warstwa logiki biznesowej, a konkretniej jakiś obiekt-usługa pozwalający na zapisywanie i usuwanie obiektów w bazie danych.
Czyli powinieneś mieć obiekt z metodą delete przyjmującą obiekt, który należy usunąć. Wewnątrz tej metody wykonasz potrzebne operacje (tj. zmiana danych w innych obiektach), a następnie wykonasz faktyczne usunięcie obiektu z bazy. Wszystko, jak zawsze, powinno być objęte transakcją. |
|
|
![]()
Post
#8
|
|
![]() Grupa: Zarejestrowani Postów: 206 Pomógł: 4 Dołączył: 2.04.2005 Ostrzeżenie: (0%) ![]() ![]() |
Jakie miejsce więc sugerujesz? Rozumiem, że RepostoryClass też nie jest dobrym miejscem na to. Pytam o konkrety, bo teoretyczne aspekty architektury znam. Chciałbym zobaczyć jak takie coś zrobić w Symfony2, jak projektujecie taką warstwę logiki biznesowej.
|
|
|
![]()
Post
#9
|
|
![]() Grupa: Zarejestrowani Postów: 6 476 Pomógł: 1306 Dołączył: 6.08.2006 Skąd: Kraków Ostrzeżenie: (0%) ![]() ![]() |
Repozytoria to w sumie nic innego jak unikalna nazwa, dla pewnej kategorii obiektów-serwisów, służących wyłącznie pobieraniu obiektów ze źródła danych (w przypadku Doctrine: bazy danych). Są więc analogiczne do obiektów typu DAO, służących utrwalaniu/usuwaniu danych w źródle danych.
W zależności od wymagań projektu można zrezygnować z części poniższych elementów i uprościć całość. 1. DAO - czyli obiekt pozwalający na zapisanie, aktualizację i usunięcie danych; Raczej na wewnętrzny użytek warstwy modelu; W przypadku, gdy korzystamy z Doctrine obiekt taki będzie właściwie wszystko przekazywał do wykonania Doctrine'owskiemu EntityManagerowi (metody persist(), delete()/remove() - nie pamiętam jaką tam nazwę ta ostatnia ma); Obiekt ten raczej nie powinien wykonywać jakiś dodatkowych operacji; Ewentualnie można w nim dodać bardzo podstawowe odczytywanie danych, najczęściej jedynie po kluczu głównym czy jakiejś tablicy właściwość => wartość. 2. Rozbudowana warstwa serwisowa/usługowa, realizująca logikę biznesową. To tutaj znajdą się usługi pozwalające na: 2.1. Wybieranie danych, na podstawie różnych kryteriów, różnymi metodami, np. $userLookupServiceA->findActiveUsersWithRange($range), $userLookupServiceB->find(array $criteria)->orderBy($property, $direction)->limit($offset, $limit)->filter(callback $filter)->getResults() czy proste $userLookupServiceC->find($pk). Te usługi mogłyby wykonywać zapytania DQL. 2.2. Zarządzenie tymi danymi, czyli ich utrwalanie i kasowanie. Takie usługi wewnętrznie będą korzystać właśnie z DAO. To tutaj powinna zostać rozpoczęta transakcja, sprawdzone uprawnienia użytkownika do wykonania takiej akcji, czy wreszcie zmodyfikowane innych obiektów w bazie danych. Jest to też dobre miejsce by wywołać jakieś zdarzenia (eventy), np. entity_a.pre_delete, entity_a.post_delete. Pod te zdarzenia, będą mogły być podpięte inne usługi - np. usługa wysyłająca emaila do użytkownika z informacją o usunięciu danych. 2.3. W końcu, faktyczna logika biznesowa, czyli np. usługa pozwalająca na przesłanie kredytów/pieniędzy pomiędzy różnymi użytkownikami, czy złożeniu zamówienia. Na przykład w przypadku, gdy w systemie istnieją użytkownicy, którzy mogą kupić/dostać tzw. kredyty, które później wymieniają na produkty/dodatkowe funkcje w serwisie, interfejs dla usługi zajmującej się operowaniem na pojedynczym koncie (kredytowym) użytkownika mógłby wyglądać tak:
4. Oczywiście wszystkie opisane powyżej elementy to interfejsy, do których należałoby utworzyć konkretną implementację. 5. Takie obiekty jak EntityManager na dobrą sprawę nigdy nie powinny pojawić się kontrolerze aplikacji. Najlepiej gdyby jedynie interfejsy (nie konkretne implementacje) były znane Jak widzisz da się to dosyć mocno rozdrobić, a 95% - jak nie więcej - aplikacji nie potrzebuje tak silnego oddzielenia tych elementów. Nie mniej jednak, Twój problem, tj. nietrywialne usunięcie obiektu z bazy danych, powinno zostać wykonane w jakiejś usłudze opisanej w punkcie #2.3. Ten post edytował Crozin 16.09.2012, 13:19:07 |
|
|
![]() ![]() |
![]() |
Aktualny czas: 21.08.2025 - 21:18 |