Doctrine Inheritance replacement

那年仲夏 提交于 2019-12-04 05:42:37

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

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.

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