15

我正在试验 PHP 的 Doctrine ORM (v1.2)。我已经定义了一个类“酒”,有两个子类“杜松子酒”和“威士忌”。我正在使用具体继承(大多数文献中的类表继承)将类映射到三个单独的数据库表。

我正在尝试执行以下操作:

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

最初,我希望 $liquors 是一个包含所有酒的 Doctrine_Collection,无论它们是威士忌还是杜松子酒。但是当我执行代码时,我得到一个空集合,尽管威士忌和杜松子酒数据库表中有几行。根据生成的 SQL,我明白了原因:ORM 正在查询“酒”表,而不是存储实际数据的威士忌/杜松子酒表。

请注意,当我将继承类型切换为列聚合(简单表继承)时,代码可以完美运行。

获得包含所有酒类的 Doctrine_Collection 的最佳方法是什么?

更新

经过一些更多的研究,看起来我期待 DoctrineUNION在幕后执行 SQL 操作以组合来自“威士忌”和“杜松子酒”表的结果集。

这称为多态查询

根据这张票,此功能在 Doctrine 1.x 中不可用。它的目标是 2.0 版本。(另见CTI的 Doctrine 2.0 文档)。

那么根据这些信息,解决这个缺陷的最干净、最有效的方法是什么?切换到单表继承?执行两个 DQL 查询并手动合并生成的 Doctrine_Collections?

4

2 回答 2

3

目前Doctrine唯一稳定有用的继承模式是column_aggregation。我在不同的项目中尝试过其他人。使用 column_aggregation,您可以模仿多态查询。一般来说,继承在 Doctrine (1.x) 中有点问题。在 2.x 中,这将发生变化,因此我们将来可能会有更好的选择。

于 2010-08-12T07:04:08.087 回答
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')

从这里开始有各种各样的变化,比如将所有酒类数据存储在子类表中,只在酒类表中存储引用和子类名称。我最不喜欢这个,因为如果你聚合公共数据,它可以让你不必为公共字段查询每个子类表。

希望这可以帮助!

于 2010-08-09T15:41:54.440 回答