我有3张桌子
People
- id -pk
- name
Roles
- id -pk
- roleName
Events
- id -pk
- title
和连接表
event_performers
- event_id -pk
- role_id -pk
- people_id -pk
一个事件有很多角色。 角色由人员执行。 角色与许多事件相关联。 一个人可以执行许多角色。
所以我想要的是,当我收到一个事件时,我可以访问与该事件相关的角色集合,并且从角色中我可以获得执行该角色的人员。
我不确定如何在Doctrine 2中进行映射?
答案 0 :(得分:21)
一周前我遇到了同样的问题。我对Doctrine IRC频道用户进行了调查,以获得最佳解决方案(或者至少是最常用的解决方案)。以下是它的完成方式:
使用@ManyToOne,$ event,$ person和$ role创建一个名为EventsPeopleRoles的新实体,其中包含三个属性。
每个关联的映射应与此类似:
/**
* @ManyToOne(targetEntity="Events", inversedBy="eventsPeopleRoles")
* @JoinColumn(name="event_id", referencedColumnName="id", nullable=false)
*/
private $event;
然后在三个相关实体的每一个中,编码关联的反面,如下所示:
/**
* @OneToMany(targetEntity="EventsPeopleRoles", mappedBy="event")
*/
private $eventsPeopleRoles;
然后,您可以选择将“$ id”属性添加到“join实体”,或者使用复合主键(如here所述)并在实体类定义中添加唯一约束注释。请注意,仅在Doctrine 2.1中支持复合外键。
我对此解决方案持怀疑态度,因为我不喜欢仅为了加入而创建实体的想法。这似乎是作弊或至少与ORM设计原则相反。但我相信这是学说专家中公认的解决方案(至少目前为止)。
答案 1 :(得分:7)
如果有人像我一样是新手,我会在@cantera中为这个伟大的答案添加一些注释:
在这三个实体的每个实体中,你必须添加他建议的代码,只需要注意" ORM \"必须包括在" ManyToOne"和#34; JoinColumn"。我还添加了#34; @ var"注释只是为了澄清可能性:
在您的实体名称=" eventsPeopleRoles"中,添加三个实体中每个实体的引用:
/**
* @var Events $event
*
* @ORM\ManyToOne(targetEntity="Events", inversedBy="eventsPeopleRoles")
* @ORM\JoinColumn(name="event_id", referencedColumnName="id", nullable=false)
*/
private $event;
/**
* @var Events $people
*
* @ORM\ManyToOne(targetEntity="Person", inversedBy="eventsPeopleRoles")
* @ORM\JoinColumn(name="person_id", referencedColumnName="id", nullable=false)
*/
private $people;
/**
* @var Role $role
*
* @ORM\ManyToOne(targetEntity="Role", inversedBy="eventsPeopleRoles")
* @ORM\JoinColumn(name="role_id", referencedColumnName="id", nullable=false)
*/
private $role;
在您的实体名称中="事件"
/**
* @var ArrayCollection $eventsPeopleRoles
*
* @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="event")
*/
private $eventsPeopleRoles;
在您的实体名称中="人物"
/**
* @var ArrayCollection $eventsPeopleRoles
*
* @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="people")
*/
private $eventsPeopleRoles;
在您的实体名称中="角色"
/**
* @var ArrayCollection $eventsPeopleRoles
*
* @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="roles")
*/
private $eventsPeopleRoles;
答案 2 :(得分:3)
@ cantera25的解决方案是正确的。
我想为它添加一个想法。
通常情况下,如果您的加入实体将加入两个以上的实体,则表明它在您的信息架构中具有相当重要的作用,应该重命名。
例如,我正在为骑马马厩工作的应用程序有一个Booking
实体。
每个Booking
至少有一个Rider
与Horse
一起预订。{/ p>
我最初设计了一个名为BookingRiderHorse
的实体,将这三个实体加在一起。
毋庸置疑,当我重新审视代码时,这将是非常混乱和难以理解的。
我将以前的Booking
实体重命名为Ride
,并将BookingRiderHorse
实体重命名为Booking
。
现在,在业务逻辑中,Bookings
已创建,且必须具有现有的Ride
,Horse
和Rider
记录。每个Booking
只有一个Horse
和Rider
,但每个Ride
可以有多个Bookings
。
这与使用具有有趣名称的连接表相同,但更容易理解,这意味着我可以处理业务逻辑而无需考虑连接的工作方式。