Doctrine ORM在EAV表上的应用

9

我计划创建我的应用程序并为模型使用ORM,但问题是,数据库中有一部分使用实体属性值表。

我很喜欢Doctrine ORM,但我不知道是否可能创建类,使其看起来像任何普通的doctrine实体,即使表实际上是EAV风格的。

是否可能在这种情况下使用Doctrine,如果可以,如何操作?


开箱即用,我表示怀疑。你可能可以自己实现。Doctrine相当可扩展。 - ZolaKt
因为根据值建立表关系(根据其数据类型连接正确的属性-值表)是不可能的(据我所知),所以使用Doctrine实现这一点应该相当棘手。 - Alain Tiemblo
2个回答

5

绝对可以实现:

建立如下关系: 对象(一对多)-> 属性值 -> 多对一 -> 属性类型


1
如果您想获取与其他表中的关系具有某个属性,该怎么办? - Nico
是的,这就是问题所在 - 几乎肯定的解决方案是您必须在代码中使用接口来获取EAV属性的属性,不幸的是,这会增加一层复杂性。 - Harry Mustoe-Playfair

3

鉴于EAV,显然使用Doctrine可以很容易地建立entityattribute之间的关系。在最复杂的情况下,我们处理一个Many to Many关系。

因此,假设我们想将属性Name映射到实体User。假设用户有且仅有一个名称,并且每个名称都属于一个用户,可以使用One to One关系来实现此链接。

但是如何建模attributevalue之间的关系?问题在于值可能具有不同的类型,甚至需要不同数量的字段才能保存其信息。

考虑到属性“name”和“phone_number”,虽然名字可能由字符串表示,但电话号码可能需要整数。或者甚至需要在单独的字段中不仅存储号码,还要存储区号。
因为EAV需要非常灵活的值表示,所以不可能将它们全部存储在数据库表的同一字段中(忽略blob、数据序列化等)。因此,大多数EAV实现使用不同的表来表示不同的值类型。
为了实现这种灵活性,Doctrine提供了继承映射。它基本上允许您扩展Doctrine实体。这样做,您可以为实体的每个子类型指定一个“鉴别器”。
/**
  * @Entity
  * @InheritanceType("JOINED")
  * @DiscriminatorColumn(name="value_type", type="string")
  * @DiscriminatorMap({"name" = "Name", "phone" = "PhoneNumber"})
*/
class Value
{
// ...
}

/** @Entity */
class Name extends Value
{
// ...
}

/** @Entity */
class PhoneNumber extends Value
{
// ...
}

“Value”类为所有值提供常见实现,即ID。每个子类(例如“Name”和“PhoneNumber”)通过它们各自特定的值扩展这些共同值,例如附加字段。
“@DiscriminatorColumn”定义父关系中存储值类型的列。
“@DiscriminatorMap”由Doctrine用于将类型从“@DiscriminatorColumn”映射到其中一个类。
可以将“属性”和“值”之间的关系指定为父类。然后,从属性中调用值将获取所有类型的值,这些值可以在运行时使用例如instanceof进行过滤(和处理)。

如果你需要1000个不同的属性,那么你必须编写1000个类吗?而且你的应用程序用户不能添加新属性吗? - Michael Käfer
1
你可以创建一个名为StringValue的类,以便用户可以添加新类型为string的值...诚然,PhoneNumber示例并不是很好。但是这个概念是EAV而不是Doctrine。 - magic_al

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接