2010-07-09 8 views
14

Eksperymentuję z Doctrine ORM (v1.2) dla PHP. Zdefiniowałem klasy "trunek", z dwiema klasami dzieci "gin" i "whisky". Używam dziedziczenia betonu (dziedziczenie tabeli klas w większości literatury) w celu odwzorowania klas na trzy oddzielne tabele bazy danych.PHP doktryna 1.2 ORM - polimorficzne zapytania z dziedziczeniem tabeli klas

Ja próbuje wykonać następujące czynności:

$liquor_table = Doctrine_Core::getTable('liquor'); 
$liquors = $liquor_table->findAll(); 

Początkowo spodziewałem $ ługi być Doctrine_Collection zawierający wszystkie trunki, czy to whisky albo gin. Ale kiedy wykonuję kod, otrzymuję pustą kolekcję, pomimo kilku rzędów w tabelach bazy danych whisky i dżinu. Na podstawie wygenerowanego kodu SQL rozumiem, dlaczego: ORM wysyła zapytanie do tabeli "alkohol", a nie do tabeli whisky/ginu, w której przechowywane są rzeczywiste dane.

Należy zauważyć, że kod działa doskonale, gdy przełączam typ dziedziczenia na agregację kolumn (proste dziedziczenie tabel).

Jaki jest najlepszy sposób uzyskania Doctrine_Collection zawierającego wszystkie trunki?

Aktualizacja

Po kilku dalszych badań, to wygląda jakbym spodziewał Doctrine do wykonywania operacji SQL UNION za kulisami do łączenia zestawów wyników z „whisky” i stoły „gin”.

Jest to tak zwane zapytanie polimorficzne .

Zgodnie z this ticket ta funkcja nie jest dostępna w Doctrine 1.x. Jest przeznaczony do wydania 2.0. (zobacz także Doctrine 2.0 docs dla CTI).

W świetle tych informacji, jaki byłby najczystszy i najskuteczniejszy sposób obejścia tego problemu? Przejść do dziedziczenia z pojedynczej tabeli? Wykonaj dwa zapytania DQL i ręcznie scalaj wynikowe Doctrine_Collections?

Odpowiedz

3

Jedynym stabilnym i użytecznym trybem dziedziczenia Doctrine w danym momencie jest column_aggregation. Próbowałem innych w różnych projektach. Dzięki column_aggregation możesz naśladować zapytania polimorficzne. Dziedziczenie w ogóle jest czymś, co jest nieco błędne w Doctrine (1.x). W wersji 2.x to się zmieni, więc możemy mieć lepsze opcje w przyszłości.

0

Napisałem (nie gotowe do produkcji) początki ORM, które zrobiłyby dokładnie to, czego szukacie chwilę temu. Po to, abym mógł mieć dowód koncepcji. Wszystkie moje badania wykazały, że w pewien sposób mieszacie kod i dane (informacje o podklasach w tabeli alkoholi).

Możesz więc napisać metodę na swojej klasie alkoholi/tabeli, która zapyta o własną tabelę. Najlepszym sposobem na pozbycie się tego, że nie wymaga sztywnego kodowania wszystkich podklas w klasie alkoholi jest posiadanie kolumny zawierającej nazwę klasy podklasy.

Sposób, w jaki rozkładasz informacje, zależy wyłącznie od Ciebie. Myślę, że najbardziej znormalizowany (i każdy może poprawić mnie, jeśli się mylę tutaj) sposobem na to jest przechowywanie wszystkich pól, które pojawiają się w twojej klasie alkoholowej w stole alkoholowym. Następnie dla każdej podklasy należy utworzyć tabelę przechowującą określone dane dotyczące typu podklasy. W tym punkcie mieszamy kod i dane, ponieważ kod odczytuje tabelę alkoholi, aby uzyskać nazwę podklasy w celu wykonania sprzężenia.

użyję samochody & rowery i pewne minimalne, jednak trywialne różnice między nimi na moim przykładzie:

Ride 
---- 
id 
name 
type 

(1, 'Sebring', 'Car') 
(2, 'My Bike', 'Bicycle') 

Bicycle 
------- 
id 
bike_chain_length 

(2, '2 feet') 

Car 
--- 
id 
engine_size 

(1, '6 cylinders') 

Nie wszystkie rodzaje wariacji stąd do przodu jak przechowywanie wszystkich danych klasy alkohol w tabeli podklasy i tylko przechowywanie nazw referencji i podklas w tabeli zawartości. Najbardziej mi się to podoba, ponieważ jeśli agregujesz wspólne dane, to oszczędza ci to konieczności odpytywania każdej tabeli podklasy dla wspólnych pól.

Mam nadzieję, że to pomoże!