Overriding inversedBy mapping in Doctrine 2 inheritance
Unidirectional / bidirectional
Doctrine 2 uses the concept of unidirectional associations and bidirectional associations.
When defining a unidirectional association you have to omit the inversedBy
parameter, because the association isn't inversed.
When defining a bidirectional association you have to use the inversedBy
parameter on the owning side (that's the side that actually contains all metadata for Doctrine to properly map the association), and you have to use the mappedBy
parameter on the inversed side (so that Doctrine knows where to look for the actual mapping metadata for the association).
So you either use both inversedBy
and mappedBy
(bidirectional) or you don't use them at all (unidirectional).
Principle of inheritance
But it is cumbersome and goes against the principle of inheritance.
I think that depends on how you look at it:
If you only look at the code (not the mapping), you are correct. Both concrete implementations of OrderTime
share a property $restaurant
(and probably getters, setters, and maybe other logic), so the principle dictates that you define that in OrderTime
.
But when you look at the mapping, you have 2 different associations: One that ties Restaurant::$collectionTimes
and CollectionTime::$restaurant
together, and one that ties Restaurant::$deliveryTimes
and DeliveryTime::$restaurant
together.
Because these are 2 different associations, it's only fair that Doctrine wants you to properly define them both.
You can still stick to principle of inheritance in the following way: Define all shared logic you need in OrderTime
, even the property $restaurant
, just don't add the mapping metadata. In the concrete implementations you can redeclare the property $restaurant
with the proper mapping metadata.
The only reason you have to redeclare the property $restaurant
in those concretes is that you're using Annotations for mapping metadata. When using Yaml or XML, you don't have to redeclare the property because the mapping metadata will be in separate files.
So in fact it's not code/logic you're defining in those concrete implementations, it's the mapping metadata.
Value Object
Those OrderTime
classes look more like Value Objects to me (not Entities): A small simple object, like money or a date range, whose equality isn't based on identity.
Doctrine will support Value Objects starting with version 2.5 (see here).
You can override inversedBy
since Doctrine 2.6. That would look like that:
/**
* @Entity
* @ORM\AssociationOverrides({
* @ORM\AssociationOverride(name="restaurant", inversedBy="collectionTimes")
* })
*/
class CollectionTime extends OrderTime
{
}
/**
* @Entity
* @ORM\AssociationOverrides({
* @ORM\AssociationOverride(name="restaurant", inversedBy="deliveryTimes")
* })
*/
class DeliveryTime extends OrderTime
{
}