2010-07-09 22 views
14

我正在嘗試PHP的Doctrine ORM(v1.2)。我已經定義了一個班級「酒」,有兩個孩子班「杜松子酒」和「威士忌」。我使用具體繼承(大多數文獻中的類表繼承)將類映射到三個獨立的數據庫表。PHP教條1.2 ORM - 具有類表繼承的多態查詢

我試圖執行以下操作:

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

最初,我預計$酒是包含所有酒類一個Doctrine_Collection,無論是威士忌或杜松子酒。但是當我執行代碼時,儘管在威士忌和杜松子酒數據庫表中有幾行,但我仍然得到一個空的集合。根據生成的SQL,我明白爲什麼:ORM查詢的是「酒」表,而不是存儲實際數據的威士忌酒/杜松子酒表。

請注意,當我將繼承類型切換爲列聚合(簡單表繼承)時,代碼完美工作。

什麼是獲得包含所有酒類的Doctrine_Collection的最佳方式?

更新

一些調查研究後,它看起來像我期待學說被執行幕後SQL UNION操作的結果集從「威士忌」和「晶晶」表結合起來。

這被稱爲多態查詢

根據this ticket,該功能在Doctrine 1.x中不可用。它註定要發佈到2.0。 (另請參閱CTI的Doctrine 2.0文檔)。

因此,根據這些信息,解決這個不足的最簡潔,最有效的方法是什麼?切換到單個表繼承?執行兩個DQL查詢並手動合併得到的Doctrine_Collections?

回答

3

目前唯一穩定有用的教條繼承模式是column_aggregation。我在其他項目中嘗試了其他人。使用column_aggregation可以模擬多態查詢。 繼承一般來說是在Doctrine(1.x)中有點錯誤。隨着2.x這將改變,所以我們可能在未來有更好的選擇。

0

我寫了一個ORM的開始(不是生產就緒),它會完成你正在尋找的內容。只是爲了讓我可以有一個概念證明。我所有的研究都確實證明你在某種程度上混合了代碼和數據(酒表中的子類信息)。

所以你可能要做的是在你的酒類/表類中寫一個方法來查詢它自己的表。 不需要硬編碼類中的所有子類,最好的辦法是在列中包含其中的子類的類名。

你如何傳播細節完全取決於你。我認爲最正常的(如果我錯了,任何人都可以糾正我)這樣做的方法是將出現在酒類中的所有字段存儲在酒類表中。然後,對於每個子類,都有一個存儲與子類類型有關的特定數據的表。 這是您混合代碼和數據的地方,因爲您的代碼正在讀酒類表以獲取子類的名稱以執行連接。

我會用汽車&自行車和我的例子它們之間的一些最小的,但瑣碎的區別:

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') 

出現的各種變化,從這裏向前像存儲在子類表中的所有白酒類數據和只在酒表中存儲參考和子類名稱。我最不喜歡這樣做,因爲如果你正在彙總公共數據,那麼你不必爲每個子類表查詢公共字段。

希望這會有所幫助!