2013-08-07 13 views
15

TłoKorzystając z narzędzi CLI Symfony 2, w jaki sposób wygenerować obiekty pobierające i ustawiające z poprawnymi podpowiedziami typów dla podklas?

Zajmuję się tworzeniem aplikacji przy użyciu Symfony 2, który jest skonstruowany tak, że „Core” pakiet określa podmioty, relacje i pól. Inne pakiety mogą następnie specjalizować podstawową funkcjonalność przez dziedziczenie, tak zwane pakiety "podrzędne".

Adnotacje Doctrine 2 zostały użyte do zdefiniowania głównej jednostki o nazwie "Pakiet". "Pakiet" łączy ze sobą projekt architektoniczny i kawałek ziemi - zasadniczo pakiet domu i ziemi. Zredukowaliśmy przykłady do bardziej podstawowej postaci, więc nie znajdziesz definicji Land i ChildLand w poniższych przykładach, ale możesz założyć, że zostały one zaimplementowane w podobny sposób.

Aktualizacja

Według użytkowników na kanale #symfony FreeNode, ten problem jest doktryna jako polecenie app/console po prostu wywołuje konsolę doktryny. Używam doktryny 2.3.

Oto schemat przedstawiający ogólną sytuację, która powoduje problem, który powinien pomóc wyobrazić sobie scenariusz:

(imgur link to full-size image) Type hinting contract breaking

Również tutaj jest link do raportu o błędzie na emisyjnej trackera doktryny : http://www.doctrine-project.org/jira/browse/DDC-2605

Update 2 - szczegółowe ERD

Th Struktura relacji między podmiotami została zakwestionowana, dlatego poniższy przykład jest lepszym przykładem struktury danych, którą wdrażamy.

Głównym wymaganiem jest ponownie posiadanie klas podstawowych, które udostępniają wspólny zestaw jednostek i pól. Klasy dziecięce w pakietach firm rozszerzają te podstawowe klasy.

Uznaliśmy EAV za długi, ale w tym podejściu spędzimy dużo więcej czasu, tworząc platformę i narzędzia do zarządzania danymi EAV, zamiast spełniać obecne wymagania biznesowe, nie będziemy mogli używać doktryny do zarządzaj jednostkami takimi, jak będą one zdefiniowane w bazie danych, itp. itd.

W miarę upływu czasu i zaczynam rozumieć ten problem lepiej, wydaje się, że jedynym problemem jest z pobierającymi i ustawiaczy generowanych przez narzędzie CLI doktryny, jak się łamią umowy typu "hinting", o których mowa poniżej. Ta struktura działa doskonale, gdy problemy te są ręcznie korygowane.

(imgur link to full-size image) Detailed data structure

Generowanie Podmioty z CLI narzędzie

Więc początkowo użyłem narzędzia wiersza polecenia ...

> app/console doctrine:generate:entity 

...do generowania odcinki Podmiot o podstawowych odwzorowań pól, a następnie ręcznie dodane relacji do ziemi (jako narzędzie nie wydają się potwierdzać relacje):

To otrzymany kod:

rdzeń jednostka Opakowanie: http://pastebin.com/3ujPT1mJ

dziecko jednostka Opakowanie: http://pastebin.com/sjAB0XJ2

generowanie pobierające i ustawiające

Następnie wygenerować z pobierające i ustawiające przez wykonanie:

> app/console doctrine:generate:entities CompanyCoreBundle 

> app/console doctrine:generate:entities CompanyChildBundle 

Które automatycznie modyfikuje podstawowych i podmiot dziecko definicje:

rdzeń podmiot Opakowanie: http://pastebin.com/kfQRxcnm

dziecko jednostka Opakowanie: http://pastebin.com/UdiPP9xX

problemu!

więc sedno problemu jest taka: Jeśli porównać funkcję setLand w wiązce podstawowej i dziecko można zobaczyć deklaracje są różne:

public function setLand(\Company\CoreBundle\Entity\Land $land = null) 
public function setLand(\Company\ChildBundle\Entity\ChildLand $land = null) 

Błędy :(

Niestety, różne podpowiedzi typu PHP powodować błędy występują ścisłe, na przykład:

PHP Fatal error: Class 'Symfony\Component\Debug\Exception\ContextErrorException' not found in ... Company/ChildBundle/Entity/ChildPackage.php on line ... 

A

Runtime Notice: Declaration of ... should be compatible with ... in ... line ... 

przyczyną błędów

Po robi jakieś badania, dlaczego to był problem, czytałem w kilku miejscach, że zmiana typów parametrów w podklasy przerwy typów parametrów umów (zobacz stanowisko: Is there a way to redefine a type hint to a descendant class when extending an abstract class?).

Opcje?

Istnieją pewne oczywiste, ale mniej niż idealne opcje:

  • mogę stłumić surowe zawiadomień dość łatwo, ale mój kierownik rozwój Graniaki perspektywą konieczności tworzenia wyjątków płatka śniegu w naszych procesów CI.
  • Mogę ręcznie edytować kod generowany przez doktrynę w celu usunięcia wszystkich typów podpowiedzi lub upewnić się, że podpowiedzi typu klasy dziecka są takie same jak klasy nadrzędne. Dzięki temu kod działa, ale widzę, że jest to nudne, chyba że piszę skrypty, aby to dla mnie zarządzać.
  • Nie mogę po prostu użyć narzędzi wiersza poleceń i ręcznie ręcznie utworzyć moje jednostki i podelementy. Wolałbym zautomatyzować to za pomocą skryptów :(

Moje pytanie !!!(na końcu)

Moje pytanie brzmi, czy można używać narzędzi wiersza poleceń do robienia tego, co próbuję tutaj zrobić? Idealnie, chciałbym móc wykonywać polecenia konsoli doktryny, aby generować encje encji i pobierające i ustawiające, bez ręcznej interwencji do naprawiania podpowiedzi typu w podklasach. Jeśli nie jest to łatwe do osiągnięcia, jaka jest najlepsza opcja?

Wdzięczność

Dzięki!

+1

pomogłoby to? http://symfony.com/doc/current/cookbook/doctrine/resolve_target_entity.html – jmlnik

+0

Nie bez drastycznego przemyślenia mojego podejścia. Po pierwsze, potrzebowałbym interfejsu dla każdego związku. Drugi i prawdopodobnie główny powód jest taki, że zgodnie z dokumentacją "ResolveTargetEntityListener może zmienić cel tylko na pojedynczy obiekt", podczas gdy ja będę musiał rozszerzyć podstawową funkcjonalność na wiele dzieci, więc będę miał "XPackage", "YPackage" itp. Dziękuję za odpowiedź, ale nie wiedziałem o tej funkcjonalności i na pewno będę ją uwzględniał w przyszłych scenariuszach. –

+0

Pytasz o kawałek kodu, w którym widać, że doktryna nie może obsłużyć sytuacji, w której odziedziczona klasa zastąpiła właściwość relacji? –

Odpowiedz

4

Nie jestem do końca pewien, co proces będziesz używać w celu określenia podmiotów, ale żeby skutecznie tworzyć podmioty persistable z doktryną takich jak GenericEngine i FordEngine, chcesz @MappedSuperclass

http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#mapped-superclasses

To odpowiednik Doctrine dla klasy abstrakcyjnej.

Istnieje kilka innych ciekawych sztuczek związanych z dziedziczeniem na tej stronie, które zostały połączone powyżej. Mogą ci pomóc.

Jeśli chodzi o generowanie tych rzeczy automatycznie, może być to wykonalne, ale powyżej mojej oceny w punktach reputacji +50. :-) Doctrine może pomóc w generowaniu szablonów kodu dla twoich bytów, ale tak naprawdę, czas projektowania jednostek i ich relacji jest lepiej spędzony niż czas wymyślania magicznej kombinacji wiersza poleceń.

(Ja, muszę podmiot Manufacturer a następnie mieć jeden-do-wielu relacja między Engine i Manufacturer. Ale nie o to pytasz. :-)

+0

Dzięki za odpowiedź. Dodam szczegółową ERD ilustrującą, w jaki sposób "Producent" nie będzie działał bez wdrożenia struktury EAV; inną puszkę robaków. Nasza struktura spełnia wszystkie wymagania biznesowe, a gdy błędy podpowiedzi typu doktryny zostaną naprawione ręcznie, działa dobrze. Odmienne myśli na temat struktur danych oznaczają, że moglibyśmy omówić ten aspekt na zawsze :-). Pod względem czasowym automatyzacja generowania klas potomnych zapewniłaby ciągłe korzyści, podobnie jak narzędzia CLI dla doktryny, które dobrze obsługują, z wyjątkiem zagadnień związanych z typowaniem.Jeśli nie używanie narzędzi naprawdę jest odpowiedzią, to zaakceptuję:/ –

+0

Dodałem zaktualizowany ERD. Jeszcze raz dziękuję za poświęcony czas. –

Powiązane problemy