I have following issue with the single table inheritance mapping for Doctrine ORM aka STI.
It seems as if it's impossible to have a oneToMany association from the STI entity to another entity.
I have 2 entities Customer and Supplier , with very similar fields. Which is why I want to use the single table inheritance option in Doctrine to get these 2 entities in one table with a simple 'type' column so to indicate what entity the row belongs to. AbstractBusiness class will serve as a base class for these 2 entities.
Consider this entity mapping for AbstractBusiness.
Axelvnk\CRMBundle\Entity\AbstractBusiness:
type: entity
table: axelvnk_crm_business
inheritanceType: SINGLE_TABLE
discriminatorColumn:
name: type
type: string
discriminatorMap:
customer: Axelvnk\CRMBundle\Entity\CustomerInterface
supplier: Axelvnk\CRMBundle\Entity\SupplierInterface
id:
id:
type: guid
generator:
strategy: UUID
fields:
vatNumber:
type: string
label:
type: string
oneToOne:
billingAddress:
targetEntity: Axelvnk\CRMBundle\Entity\AddressInterface
joinColumn:
name: billing_address_id
referencedColumnName: id
cascade: ["all"]
oneToMany:
addresses:
targetEntity: Axelvnk\CRMBundle\Entity\AddressInterface
mappedBy: business
cascade: ["all"]
This would be the mapping for the Customer entity
Axelvnk\CRMBundle\Entity\Customer:
type: entity
This would be the mapping for the Supplier entity
Axelvnk\CRMBundle\Entity\Supplier:
type: entity
For the time being no additional fields. But it wouldn't make a difference for this issue.
Now the AbstractBusiness::billingAddress property refers to an instance of an Address entity. Which is mapped like this :
Axelvnk\CRMBundle\Entity\Address:
type: entity
table: axelvnk_crm_address
id:
id:
type: guid
generator:
strategy: UUID
fields:
streetAndNumber:
type: string
city:
type: string
manyToOne:
business:
targetEntity: Axelvnk\CRMBundle\Entity\AbstractBusiness
inversedBy: addresses
joinColumn:
name: business_id
referencedColumnName: id
As you can see the Address::business property refers back to the STI entity, being the AbstractBusiness. This can be either a Supplier or a Customer depending on the owning side..
I would expect doctrine to resolve which entity class to hydrate to since it knows AbstractBusiness is a STI entity and the discriminator map is in place. After querying the business table with the business_id in the address table, it should be able to figure out the class based on the "type" column in the address table, right? But apparently it doesn't. I can't map back to the STI entity because doctrine can't make proxy classes from Abstract classes, which makes sense I guess.
But my question now is, what is the right way to map back to the STI entity? Or is this just impossible in Doctrine?
Thank you for your answers!
So apparently, using interfaces in the discriminatorMap and then using the doctrine target entity resolver to replace these interfaces with concrete classes works perfectly to persist entities, but to fetch them, it can't figure out what class to hydrate...
So the solution : always use concrete classes in the discriminatorMap...
There's an open issue on github to support resolving the classes/interfaces in the discriminator map the same way it works for targetEntity properties : https://github.com/doctrine/orm/issues/7622
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.