Doctrine 2 how to properly map multi-level inheritance

2.2k Views Asked by At

I have multi-level inheritance doctrine entity like this:

/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="type", type="string")
 * @ORM\DiscriminatorMap({"customer" = "CustomerUser",
 * "admin" = "AdminUser", "stock" = "StockUser"})
 */
abstract class User { ... }

/** @ORM\Entity */
abstract class EmployeeUser extends User { ... }

/** @ORM\Entity */
class AdminUser extends EmployeeUser { ... }

/** @ORM\Entity */
class StockUser extends EmployeeUser { ... }

However it does not work this way, fields of EmployeeUser are neither read from database nor persisted.

I've found out that it works when I specify the discriminator map this way:

 * @ORM\DiscriminatorMap({"customer" = "CustomerUser",
 * "admin" = "AdminUser", "stock" = "StockUser", "EmployeeUser"})

it starts to work this way (there is no need to specify discriminator key for EmployeeUser - as it is abstract and will never be instantiated), but

I don't like when magic happen that I don't understand enough :) so my question is: is this a proper solution? To just let Doctrine know this way that this class is somehow included in inheritance hierarchy? Or should it be done anyhow else?

I haven't found any mention about how to do multiple level entity class inheritance in Doctrine docs.

1

There are 1 best solutions below

1
On BEST ANSWER

I have same situation. I need more than one level of inheritance. That in your case is expected behavior, you need to list all of mapped classes in DiscriminatorMap.

My case don't have that map because I am using native transformation of ClassName to type key and it's working for classes on all inheritance level.

abstract ClassA
abstract ClassB extends ClassA
   - protected someName
ClassC extends ClassB

When I save ClassC obj I have that property someName saved. You can try yourself without discriminatory map and see that all classes are mapped and save.

EDIT :

One more thing if you want to avoid multilevel inheritance you can always use trait for that. Just group the props to trait and add it to entity. There are good example of trait usage in DoctrineBehaviors bundle. There are using it to import additional capabilities to entities like blamable, loggable etc.