如何在 Symfony 中设置 Doctrine 的类继承?

pay*_*ing 4 doctrine symfony

我的问题是,我无法理解 Doctrine 类继承中的 DiscriminatorColumn 和 DiscriminatorMap。

我有一个被视为父类/表的产品实体。

有多个继承产品实体的子实体。(型号、零件和选项)

我觉得我应该能够使用主键来链接两个表......但是我该如何使用 DiscriminatorColumn 来做到这一点?

这是我想要发生的事情的总体思路......

从数据库获取所有模型对象,同时继承产品父实体

SELECT object 
FROM parts_object parts
LEFT JOIN products_object po
ON parts.product_fk = po.product_id
Run Code Online (Sandbox Code Playgroud)

或者...从数据库获取所有零件对象,同时继承产品父实体

SELECT object 
FROM parts_object parts
LEFT JOIN products_object po
ON parts.product_fk = po.product_id
Run Code Online (Sandbox Code Playgroud)

理想情况下,我希望使用 Doctrine 而不是一些自定义 SQL 来完成此操作。

我是否需要为父表设置一个“类型”列,以便每一行定义它是零件、模型还是选项?

教义继承文档

Art*_*iel 5

好的,我会尝试尽可能简单地解释这一点。

让我们从DiscriminatorColumn

正如它所说,鉴别器列基本上是数据库中的一列。它用于存储一个键,如果您愿意的话,它有助于根据您的配置识别您当前正在查询的对象类型DiscriminatorMap

DiscriminatorMap是将每个键映射到实体的方式。你说你有以下内容

  • 产品[父]
  • 模型[父母的孩子]
  • 部分[父母的孩子]
  • 选项[父母的孩子]

然后,您的鉴别器图应如下所示,例如:

@DiscriminatorMap({
    "model" = "AppBundle\Entity\Model", 
    "Part" = "AppBundle\Entity\Part",
    "Option" = "AppBundle\Entity\Option"
})
Run Code Online (Sandbox Code Playgroud)

始终注意映射中的最后一个定义。最后一行必须以逗号结尾!

截至目前,InheritanceType我建议您使用@InheritanceType("JOINED"),因为这将使您的每个子类都有一个表。

每个子类都必须扩展您的Product实体类,这显然是父类。由于继承映射,每个子类不得定义属性。$id

然后按特定类型查询记录带有以下查询:

"SELECT product FROM AppBundle\Entity\Product product WHERE product INSTANCE OF AppBundle\Entity\Part"
Run Code Online (Sandbox Code Playgroud)

该查询将仅搜索映射到该实体的记录。

如果您有任何疑问,请随时询问。

编辑截至新评论

-----------------------

多一点解释。您不需要在实体映射中创建任何额外的属性/列。当您添加此注释原则时,@DiscriminatorColumn(name="discr", type="string")将自动为您创建该列。此示例中的列将以discr类型命名VARCHAR

我还是不明白用什么来连接表。教条如何知道链接产品和型号之间的 id

关于这一部分。如果您使用@InheritanceType("JOINED")此选项,则意味着您的GeneratedValueID 将在您的主要实体 - 中设置Product。然后,每个扩展的子实体Product都会自动获得相同的 ID,这就是为什么您不需要$id在子实体中指定属性。

最后,例如,如何检查当前正在查看的实体类型。考虑以下场景,您的每个子实体都会扩展Product,我们将对记录执行虚拟搜索:

$product = $entityManager->find('AppBundle:Product', 1); // example
Run Code Online (Sandbox Code Playgroud)

现在,如果你真的去做,var_dump($product)你会发现一些有趣的事情。Model该对象将是,Part或的实例Option,因为这些实体中的每一个都在您的鉴别器映射中定义,并且 Doctrine 会根据该实体自动映射您的记录。稍后,这在以下情况下会派上用场:

if( $product instanceof \AppBundle\Entity\Part ) {
    // do something only if that record belongs to part.
}
Run Code Online (Sandbox Code Playgroud)