主义2多对多有三个实体和联接表

Aar*_*uza 11 doctrine many-to-many doctrine-orm

我有3张桌子

People
 - id -pk
 - name

Roles
 - id -pk
 - roleName

Events
 - id -pk
 - title
Run Code Online (Sandbox Code Playgroud)

和一个连接表

event_performers
 - event_id -pk
 - role_id -pk
 - people_id -pk
Run Code Online (Sandbox Code Playgroud)

一个事件有很多角色.角色由人员执行.角色与许多事件相关联.一个人可以执行许多角色.

所以我想要的是,当我获得一个事件时,我可以访问与该事件相关的角色集合,并且从角色中我可以获得执行角色的人员.

我不确定如何在Doctrine 2中进行映射?

can*_*era 22

一周前我遇到了同样的问题.我对Doctrine IRC频道用户进行了调查,以获得最佳解决方案(或者至少是最常用的解决方案).以下是它的完成方式:

使用@ManyToOne,$ event,$ person和$ role创建一个名为EventsPeopleRoles的新实体,其中包含三个属性.

每个关联应该映射类似于:

/**
 * @ManyToOne(targetEntity="Events", inversedBy="eventsPeopleRoles")
 * @JoinColumn(name="event_id", referencedColumnName="id", nullable=false)
 */
private $event;
Run Code Online (Sandbox Code Playgroud)

然后在三个相关实体的每一个中,编码关联的反面,如下所示:

/**
 * @OneToMany(targetEntity="EventsPeopleRoles", mappedBy="event")
 */
private $eventsPeopleRoles;
Run Code Online (Sandbox Code Playgroud)

然后,您可以选择向"连接实体"添加$ id属性,或者使用此处所述的复合主键,并在实体类定义中添加唯一约束注释.请注意,仅在Doctrine 2.1中支持复合外键.

我对这个解决方案持怀疑态度,因为我不喜欢仅为了连接而创建实体的想法.这似乎是作弊或至少与ORM设计原则相反.但我相信,这是学说专家中公认的解决方案(至少目前为止).


ale*_*eph 7

如果有人和我一样是新手,我会在@cantera中为这个伟大的答案添加一些注释:

在三个实体中的每个实体中,您必须添加他建议的代码,只需要注意在"ManyToOne"和"JoinColumn"之前必须包含"ORM".我还添加了"@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;
Run Code Online (Sandbox Code Playgroud)

在您的实体名称中="事件"

/**
 * @var ArrayCollection $eventsPeopleRoles
 *
 * @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="event")
 */
private $eventsPeopleRoles;
Run Code Online (Sandbox Code Playgroud)

在您的实体名称中="人物"

/**
 * @var ArrayCollection $eventsPeopleRoles
 *
 * @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="people")
 */
private $eventsPeopleRoles;
Run Code Online (Sandbox Code Playgroud)

在您的实体名称中="角色"

/**
 * @var ArrayCollection $eventsPeopleRoles
 *
 * @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="roles")
 */
private $eventsPeopleRoles;
Run Code Online (Sandbox Code Playgroud)


Lew*_*ett 5

@cantera25 的解决方案是正确的。

我想补充一点。

通常,如果您的连接实体将两个以上的实体连接在一起,则表明它在您的信息架构中扮演着非常重要的角色,应该重命名。

例如,我正在为一个马厩工作的应用程序有一个Booking实体。

每个Booking人至少有一个RiderHorse在为该预订骑一辆。

我最初设计了一个名为 的实体BookingRiderHorse,将这三个实体连接在一起。

不用说,当我稍后重新访问代码时,这会非常混乱且难以理解。

我将之前的Booking实体重命名为Ride,并将BookingRiderHorse实体重命名为Booking

现在在业务逻辑中,Bookings被创建并且必须有一个现有的Ride,HorseRider记录。每个Booking只有一个HorseRider,但每个都Ride可以有多个Bookings

这与使用具有有趣名称的连接表相同,但更容易理解并且意味着我可以处理业务逻辑而无需考虑连接如何工作。