我正在试验PHP的Doctrine ORM(v1.2)。我已经定义了一个班级“酒”,有两个孩子类“杜松子酒”和“威士忌”。我使用具体的继承(大多数文献中的类表继承)将类映射到三个单独的数据库表。
我正在尝试执行以下操作:
$liquor_table = Doctrine_Core::getTable('liquor');
$liquors = $liquor_table->findAll();
最初,我预计$ liquors是一个包含所有酒类的Doctrine_Collection,无论它们是威士忌还是杜松子酒。但是当我执行代码时,我得到一个空集合,尽管在威士忌和杜松子酒数据库表中有几行。基于生成的SQL,我理解为什么:ORM查询“酒”表,而不是存储实际数据的威士忌/杜松子酒表。
请注意,当我将继承类型切换到列聚合(简单表继承)时,代码可以正常工作。
获取包含所有酒类的Doctrine_Collection的最佳方法是什么?
更新
经过一些研究后,看起来我希望Doctrine在幕后执行SQL UNION
操作,以组合“威士忌”和“杜松子酒”表中的结果集。
这称为多态查询。
根据this ticket,Doctrine 1.x中没有此功能。它注定要发布2.0版本。 (另请参阅CTI的Doctrine 2.0文档。)
因此,根据这些信息,解决这一缺陷的最简洁,最有效的方法是什么?切换到单表继承?执行两个DQL查询并手动合并生成的Doctrine_Collections?
答案 0 :(得分:3)
目前Doctrine唯一稳定且有用的继承模式是column_aggregation。我在不同的项目中尝试过其他人。使用column_aggregation,您可以模仿多态查询。 一般来说,继承在Doctrine(1.x)中有点麻烦。 2.x会改变,所以我们将来可能有更好的选择。
答案 1 :(得分: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')
从这里开始有各种各样的变化,比如在子类表中存储所有的酒类数据,并且只在白酒表中存储引用和子类名称。我最喜欢这个,但是如果你正在聚合公共数据,它将使你不必查询公共字段的每个子类表。
希望这有帮助!