7

目前,我们正在使用 Zend Framework 2 和 Doctrine 2 开发一个非常灵活和模块化的应用程序。在这个应用程序中,有多个 Doctrine 实体,例如,假设Product模块中的实体Products。该模块Products是产品管理的基本/默认模块。

我们希望能够Products为客户 ( XProducts) 创建自定义模块。因此,我创建了一个新实体XProduct(带有一些额外的字段),它扩展了Product.

因此,如果启用了自定义模块,我想使用XProductand else Product,但永远不要一起使用(在同一个项目中)。

如果我用 @Entity 注释两个实体,它会部分工作;例如findAll工作完美,但find不起作用:创建的 SELECT 语句包含正确的列,但 WHERE 子句是错误的。例如:

SELECT t1.id AS id2, t1.name AS name3 FROM products t1 WHERE t0.id = ?

我猜t1是 forProductXt0forProduct但我不知道为什么这些列是正确的 ( t1) 但 where 子句不是 ( t0)。

我知道 Doctrine 提供了单表继承来实现继承,但因此必须有一个 DiscriminatorColumn 并在基本/默认实体处定义 DiscriminatorMap。这不适合我们,因为如果我们为客户添加新的自定义模块(这不是我们想要的......),我们需要更改我们的基本/默认模块。

有没有人知道解决这个问题的线索?谢谢!

4

2 回答 2

7

我终于解决了这个问题。对于所有默认/基类,我创建了一个额外的抽象 MappedSuperclass(如 Jurian Sluiman 所述)。例如,对于Product客户的特定实体,我需要以下内容:

  • AbstractProduct(包含所有默认/基本功能)
  • 产品(默认/基类,为空并扩展 AbstractProduct)
  • XProduct(包含为我们的客户提供的额外功能并扩展了 AbstractProduct)

为了解决 MappedSuperclass 上的关联问题,我参考了抽象类,例如: @ORM\OneToOne(targetEntity="ProductManagement\Entity\AbstractProduct")

然后我使用 Doctrine 的 EntityResolver(参见http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/resolve-target-entity-listener.html)来映射一个抽象类(或接口)与真实实体的关联(取决于配置):

'entity_resolver' => array(
    'orm_default' => array(
        'resolvers' => array(
            // Note: Use only one
            'ProductManagement\Entity\AbstractProduct' => 'ProductManagement\Entity\Product', // Default
            'ProductManagement\Entity\AbstractProduct' => 'XProductManagement\Entity\XProduct', // For customer X
        )
    )
)

这样,我就可以为我的客户用特定实体覆盖我的实体,而无需更改默认/基本模块和实体(这正是我所寻找的)。

于 2013-07-18T09:49:05.393 回答
3

我们使用这种模式以及它与最容易使用的 Doctrine 一起使用(尽管使用很多丑陋的代码可以使 OOP 变得更好)。以我们的投资组合模块为例,其中一个Portfolio实例可以占用多个Item实例。

我们使用Portfolio从映射的超类扩展的实体AbstractPortfolio。如果我们有一个需要特殊字段的客户端,我们会创建一个ClientPortfolio扩展映射的超类,因此它会正确地重载所有属性。

类名在配置中指定,并且该字符串用于例如存储库的工厂。您永远不会加载Portfolio存储库,但ClientPortfolio即使您以默认组合的名称从服务管理器请求存储库类,也始终会加载。

此方法可以与此处的存储库功能一起正常工作(尽管此类是 anItem而不是 的存储库Portfolio)。我不会使用单表继承,因为您不使用多个实体。至少,这是我们的情况。

于 2013-07-11T20:20:56.867 回答