在Doctrine 2继承中覆盖inversedBy映射 [英] Overriding inversedBy mapping in Doctrine 2 inheritance
问题描述
我有以下实体:
class Restaurant
{
/**
* @OneToMany(targetEntity="CollectionTime", mappedBy="restaurant")
*/
protected $collectionTimes;
/**
* @OneToMany(targetEntity="DeliveryTime", mappedBy="restaurant")
*/
protected $deliveryTimes;
}
映射到同一个实体的两个子类:
Mapping to two subclasses of the same entity:
/**
* @Entity
* @InheritanceType("SINGLE_TABLE")
* @ORM\DiscriminatorMap({
* "CollectionTime" = "CollectionTime",
* "DeliveryTime" = "DeliveryTime"
* })
*/
abstract class OrderTime
{
/**
* @ManyToOne(targetEntity="Restaurant")
*/
protected $restaurant;
}
/**
* @Entity
*/
class CollectionTime extends OrderTime
{
}
/**
* @Entity
*/
class DeliveryTime extends OrderTime
{
}
现在问题是, doctrine orm:validate-schema
报告以下错误:
Now the problem is, doctrine orm:validate-schema
reports the following errors:
字段Restaurant#collectionTimes是双向关系的反面,但指定的mappedBy目标实体CollectionTime#餐厅上的关联不包含所需的inversedBy = collectionTimes属性。
The field Restaurant#collectionTimes is on the inverse side of a bi-directional relationship, but the specified mappedBy association on the target-entity CollectionTime#restaurant does not contain the required 'inversedBy=collectionTimes' attribute.
字段Restaurant#deliveryTimes位于双向关系,但目标实体DeliveryTime#餐厅上指定的mappedBy关联不包含所需的inversedBy = deliveryTimes属性。
The field Restaurant#deliveryTimes is on the inverse side of a bi-directional relationship, but the specified mappedBy association on the target-entity DeliveryTime#restaurant does not contain the required 'inversedBy=deliveryTimes' attribute.
简而言之,Doctrine期望每个 mappedBy
在另一边有一个 inversedBy
。
In short, Doctrine expects every mappedBy
to have an inversedBy
on the other side.
唯一的解决方案到目前为止,请将 OrderTime :: $ restaurant
属性和映射到 CollectionTime
和 DeliveryTime
,只是为了能够添加正确的 inversedBy
映射:
The only solution I can see so far is to move the OrderTime::$restaurant
property and mapping to CollectionTime
and DeliveryTime
, just to be able to add the proper inversedBy
mapping:
abstract class OrderTime
{
}
/**
* @Entity
*/
class CollectionTime extends OrderTime
{
/**
* @ManyToOne(targetEntity="Restaurant", inversedBy="collectionTimes")
*/
protected $restaurant;
}
/**
* @Entity
*/
class DeliveryTime extends OrderTime
{
/**
* @ManyToOne(targetEntity="Restaurant", inversedBy="deliveryTimes")
*/
protected $restaurant;
}
但这很麻烦,违反了继承原则。
But it is cumbersome and goes against the principle of inheritance.
是否有一种方法可以覆盖子类中的 inversedBy
属性,而无需(重新)声明整个属性在子类?
Is there a way to just override the inversedBy
attribute in the subclasses, without having to (re)declare the whole property in the subclass?
我已经研究了 @ AssociationOverrides 和 @ AttributeOverrides ,但它们似乎没有为此设计。
I've looked into @AssociationOverrides and @AttributeOverrides, but they don't seem to be designed for this purpose.
推荐答案
单向/双向
Doctrine 2使用单向关联和双向关联。
定义单向关联时,必须省略 inversedBy
参数,因为关联不被反转。
When defining a unidirectional association you have to omit the inversedBy
parameter, because the association isn't inversed.
定义双向关联时,必须使用 c $ c>参数 c> >(这是实际包含Doctrine的所有元数据以正确映射关联的一面),您必须使用
>>
参数在反转方面(以便Doctrine知道在哪里查找关联的实际映射元数据。)
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).
所以您既可以使用 inversedBy
和 mappedBy
(双向)或您
So you either use both inversedBy
and mappedBy
(bidirectional) or you don't use them at all (unidirectional).
但是这是麻烦的,违背了继承的原则。
But it is cumbersome and goes against the principle of inheritance.
我认为这取决于你看看它:
I think that depends on how you look at it:
如果你只看代码(而不是映射),你是正确的。 OrderTime
的具体实现共享一个属性 $ restaurant
(可能是getter,setter和其他逻辑),所以该原则规定您在 OrderTime
中定义。
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
.
但是,当您查看映射时,您有2个不同的关联:将 Restaurant :: $ collectionTimes
和 CollectionTime :: $ restaurant
,而一个连接 Restaurant :: $ deliveryTimes
和 DeliveryTime :: $ restaurant
在一起。
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.
因为这是两个不同的关联,所以Doctrine希望你们正确定义它们是公平的。
Because these are 2 different associations, it's only fair that Doctrine wants you to properly define them both.
你仍然可以坚持原则的继承方式:在 OrderTime
中定义所需的所有共享逻辑,即使是属性 $ restaurant
,只是不添加映射元数据。在具体实现中,您可以使用适当的映射元数据重新声明属性 $ restaurant
。
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.
唯一的原因要重新声明这些混合物中的属性 $ restaurant
,那么您正在使用注释来映射元数据。当使用Yaml或XML时,您不必重新声明属性,因为映射元数据将在不同的文件中。
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.
那些 OrderTime
类似于价值对象给我(而不是实体):一个小的简单对象,如金钱或日期范围,其平等不基于身份。
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将支持从2.5版开始的Value对象(参见此处)。
Doctrine will support Value Objects starting with version 2.5 (see here).
这篇关于在Doctrine 2继承中覆盖inversedBy映射的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!