我正计划创建我的应用程序并为模型使用 ORM,但问题是,数据库的一部分使用实体-属性-值表。
我非常喜欢 Doctrine ORM,但我不知道是否有可能创建看起来像任何普通学说实体的类,而实际上连接到的表是 EAV 样式。
是否可以在这方面使用 Doctrine,如果可以,如何使用?
我正计划创建我的应用程序并为模型使用 ORM,但问题是,数据库的一部分使用实体-属性-值表。
我非常喜欢 Doctrine ORM,但我不知道是否有可能创建看起来像任何普通学说实体的类,而实际上连接到的表是 EAV 样式。
是否可以在这方面使用 Doctrine,如果可以,如何使用?
绝对有可能:
有这样的关系:对象(一对多)-> AttributeValue -> 多对一-> AttributeType
鉴于EAVentity
,如何建立和attribute
使用学说之间的关系似乎是显而易见的。在最复杂的情况下,我们处理多对多关系。
所以假设我们想将一个属性映射Name
到一个实体User
。假设一个用户只有一个名字并且每个名字都属于一个用户,这个链接可以使用一对一关系存档
attribute
但是如何建模和之间的关系value
?问题是值可以是不同的类型,甚至需要不同数量的字段来保存它们的信息。
考虑属性name
和phone_number
。虽然名称可能由字符串表示,但电话号码可能需要一个整数。或者甚至需要在单独的字段中不仅有号码而且还需要区号。
因为 EAV 需要非常灵活的值表示,所以不可能将它们全部存储在数据库表的同一字段中(忽略 blob、数据序列化等)。因此,大多数 EAV 实现使用不同的表来表示不同的值类型。
为了达到这种灵活性,学说特征继承映射。它基本上允许您扩展学说实体。这样做你discriminator
为你的实体的每个子类型指定一个:
/**
* @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
类型从 映射@DiscriminatorColumn
到这些类之一。attribute
和之间的关系value
可以指定给父类。然后从属性调用值将获取所有类型的值,这些值可以在运行时使用例如instanceof进行过滤(和处理)。