Doctrine Inheritance replacement

回眸只為那壹抹淺笑 提交于 2019-12-06 02:03:49

问题


Currenty we're developing a very flexible and modular application with Zend Framework 2 and Doctrine 2. In this application there are multiple Doctrine entities, for example let's say the entity Product in the module Products. This module Products is the base/default module for product management.

We want to be able to create a custom Products module for a customer (XProducts). Therefore I created a new entity, XProduct (with some extra fields) which extends Product.

So if the custom module is enabled I want to use XProduct and else Product, but never together (in the same project).

If I annotate both entities with @Entity it works partially; for example findAll works perfect, but find doesn't work: the created SELECT statement contains the correct columns, but the WHERE clause is wrong. For example:

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

I guess t1 stands for ProductX and t0 for Product but I can't figure out why the columns are correct (t1) but the where clause isn't (t0).

I'm aware that Doctrine provides Single Table Inheritance to achieve inheritance, but therefore it's necessary to have a DiscriminatorColumn and to define the DiscriminatorMap at the base/default entity. This won't fit for us, because we need to change our base/default module if we add a new custom module for a customer (and that's not what we want...).

Does anyone have a clue on fixing this problem? Thanks!


回答1:


I finally fixed this problem. For all default/base class I created an extra abstract MappedSuperclass (as Jurian Sluiman mentioned). For example, for a specific Product entity for a customer I need the following:

  • AbstractProduct (contains all default/base functionalities)
  • Product (default/base class which is empty and extends AbstractProduct)
  • XProduct (which contains extra functionalities for our customer and extends AbstractProduct)

To fix the problems with associations on a MappedSuperclass I refer to the abstract class, for example: @ORM\OneToOne(targetEntity="ProductManagement\Entity\AbstractProduct")

I then use Doctrine's EntityResolver (see http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/cookbook/resolve-target-entity-listener.html) to map an abstract class (or interface) association to a real entity (depending on the configuration):

'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
        )
    )
)

This way I'm able to override my entities with specific entities for my customers, without changing the default/base module and entities (which is exactly what I was looking for).




回答2:


We use this pattern as well as it's with Doctrine the easiest to work with (though it can be made OOP wise much better with a lot of ugly code). Take an example of our Portfolio module where a Portfolio instance can take up multiple Item instances.

We work with a Portfolio entity which extends from the mapped superclass AbstractPortfolio. If we have a client requiring a special field, we create a ClientPortfolio extending the mapped superclass, so it overloads all properties correctly.

The class name is specified in the config and that string is used in for example the factory for the repository. You never load the Portfolio repository, but always load the ClientPortfolio even when you request the repository class from the service manager under the name of the default portfolio.

This method can work fine with repository functions like here (though this class is the repository for an Item and not the Portfolio). I would not use single table inheritance as you do not use multiple entities besides each other. At least, that is our case.



来源:https://stackoverflow.com/questions/17588682/doctrine-inheritance-replacement

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!