Доктрина 2 многие ко многим с тремя сущностями и таблицей объединения
у меня есть 3 таблицы
People
- id -pk
- name
Roles
- id -pk
- roleName
Events
- id -pk
- title
и присоединить таблицу
event_performers
- event_id -pk
- role_id -pk
- people_id -pk
событие имеет много ролей. Роль выполняет человек. Роль связана со многими событиями. Человек может выполнять множество ролей.
Итак, я хотел бы, чтобы, когда я получаю событие, я мог получить доступ к коллекции ролей, связанных с этим событием, и из ролей я могу получить человека, который выполнил роль.
Я не уверен, как я бы пошел о отображении этого в доктрине 2 ?
3 ответов
я столкнулся с этой же проблемой неделю назад. Я опросил пользователей канала IRC доктрины для лучшего решения (или, по крайней мере, тот, который наиболее часто практикуется). Вот как это делается:
создайте новую сущность с именем что-то вроде EventsPeopleRoles с тремя свойствами, сопоставленными с помощью @ManyToOne, $event, $person и $role.
каждая ассоциация должна быть сопоставлена аналогично этому:
/**
* @ManyToOne(targetEntity="Events", inversedBy="eventsPeopleRoles")
* @JoinColumn(name="event_id", referencedColumnName="id", nullable=false)
*/
private $event;
затем в каждом из трех связанных сущностей, код обратная сторона ассоциации такая:
/**
* @OneToMany(targetEntity="EventsPeopleRoles", mappedBy="event")
*/
private $eventsPeopleRoles;
затем у вас есть выбор либо добавить свойство $id к вашей "сущности join", либо использовать составной первичный ключ, как описано здесь и добавление уникальной аннотации ограничения в определение класса сущностей. Обратите внимание, что составные внешние ключи поддерживаются только начиная с доктрины 2.1.
Я скептически относился к этому решению, потому что мне не нравится идея создания сущности только для целей соединения. Это похоже на обман или, по крайней мере, в отличие от принципов дизайна ORM. Но я уверен, что это принятое решение (по крайней мере, пока) среди экспертов по Доктрине.
если кто-то такой же Новичок, как и я, я просто добавлю несколько аннотаций к этому замечательному ответу @cantera:
в каждом из трех объектов вы должны добавить код, который он предложил, только позаботьтесь о том, чтобы "ORM" должен быть включен перед "ManyToOne" и "JoinColumn". Я также добавил аннотации "@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;
@cantera25 прямо.
я хочу добавить к этому мысль.
обычно, если ваш объект join будет объединять более двух объектов вместе, это указывает на то, что он играет довольно важную роль в вашей информационной архитектуре и должен быть переименован.
например, приложение я работаю на конюшни есть Booking
сущности.
каждого Booking
есть по крайней мере один Rider
кто едет один Horse
за это бронирование.
я первоначально разработал сущность под названием BookingRiderHorse
, чтобы соединить эти три вместе.
Излишне говорить, что это было бы довольно беспорядочно и трудно понять позже, когда я вернусь к коду.
я переименовал бывший Booking
сущности Ride
и переименовано в BookingRiderHorse
сущности Booking
.
теперь в бизнес-логике,Bookings
создаются и должны иметь существующий Ride
, Horse
и Rider
запись. Каждый Booking
есть только один Horse
и Rider
, но каждый Ride
может быть много Bookings
.
это то же самое, что использовать таблицу соединений с забавным именем, но гораздо проще понять и означает, что я могу работать над бизнес-логикой без необходимости думать о том, как работают соединения.