2011-10-26 31 views
9

Tôi có 3 bảngthuyết 2 Nhiều người đến với Nhiều Ba Đối tượng và Tham Bảng

People 
- id -pk 
- name 

Roles 
- id -pk 
- roleName 

Events 
- id -pk 
- title 

và một bảng tham gia

event_performers 
- event_id -pk 
- role_id -pk 
- people_id -pk 

Một sự kiện có nhiều vai trò. Một vai trò được thực hiện bởi một người. Vai trò được liên kết với nhiều Sự kiện. Một người có thể thực hiện nhiều vai trò. Vì vậy, những gì tôi muốn là khi tôi nhận được một sự kiện tôi có thể truy cập một bộ sưu tập các Vai trò liên quan đến sự kiện đó, và từ các Vai trò, tôi có thể nhận được Người thực hiện Vai trò.

Tôi không chắc chắn làm thế nào tôi sẽ đi về lập bản đồ này trong Doctrine 2?

Trả lời

18

Tôi đã gặp sự cố tương tự này khoảng một tuần trước. Tôi đã thăm dò ý kiến ​​người dùng kênh Doctrine IRC để có giải pháp tốt nhất (hoặc ít nhất là giải pháp được sử dụng phổ biến nhất). Dưới đây là cách thực hiện:

Tạo đối tượng mới có tên là EventsPeopleRoles với ba thuộc tính được ánh xạ bằng @ManyToOne, $ event, $ person và $ role.

Mỗi hiệp hội nên được ánh xạ tương tự như sau:

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

Sau đó, trong mỗi một trong ba đơn vị liên quan, mã phía nghịch đảo của hiệp hội như thế này:

/** 
* @OneToMany(targetEntity="EventsPeopleRoles", mappedBy="event") 
*/ 
private $eventsPeopleRoles; 

Bạn sau đó có lựa chọn thêm thuộc tính $ id vào "thực thể tham gia" của bạn hoặc sử dụng khóa chính kết hợp như được mô tả here và thêm chú thích ràng buộc duy nhất trong định nghĩa lớp thực thể. Lưu ý rằng các khóa ngoài tổng hợp chỉ được hỗ trợ bắt đầu trong Doctrine 2.1.

Tôi đã hoài nghi về giải pháp này vì tôi không thích ý tưởng tạo một thực thể chỉ vì mục đích tham gia. Nó có vẻ như gian lận hoặc ít nhất là trái ngược với nguyên tắc thiết kế ORM. Nhưng tôi tin rằng đây là giải pháp được chấp nhận (ít nhất là hiện nay) trong số các chuyên gia Doctrine.

+0

Cảm ơn bạn đã trả lời, tôi sẽ thử cách này và cho bạn biết cách tôi tiếp tục. –

+0

Hoàn hảo. Cảm ơn! –

+0

Điều này dường như hoạt động hoàn hảo cho tôi ... Cảm ơn bạn đã chia sẻ! – jfgrissom

3

giải pháp của @ cantera25 là đúng.

Tôi muốn thêm suy nghĩ vào nó.

Thông thường, nếu thực thể tham gia của bạn sẽ tham gia nhiều hơn hai thực thể với nhau, đó là dấu hiệu cho thấy nó có vai trò quan trọng trong kiến ​​trúc thông tin của bạn và cần được đổi tên.

Ví dụ: một ứng dụng tôi đang làm việc cho chuồng ngựa có một thực thể Booking.

Mỗi Booking có ít nhất một Rider người đang cưỡi Horse cho đặt chỗ đó.

Tôi ban đầu thiết kế một thực thể được gọi là BookingRiderHorse, để kết hợp ba thứ này lại với nhau.

Không cần phải nói, điều đó sẽ khá lộn xộn và khó hiểu sau này khi tôi truy cập lại mã.

Tôi đã đổi tên thành thực thể Booking trước thành Ride và đổi tên thành đối tượng BookingRiderHorse thành Booking.

Bây giờ trong logic nghiệp vụ, Bookings được tạo và phải có bản ghi hiện tại Ride, HorseRider. Mỗi Booking chỉ có một HorseRider, nhưng mỗi Ride đều có thể có nhiều Bookings.

Điều này giống như sử dụng bảng nối với tên hài hước, nhưng dễ hiểu hơn và có nghĩa là tôi có thể làm việc trên logic nghiệp vụ mà không cần phải suy nghĩ về cách hoạt động của các kết nối.

5

Trong trường hợp ai đó là như người mới như tôi, tôi sẽ chỉ cần thêm một vài chú thích cho câu trả lời tuyệt vời này bởi @cantera:

Trong mỗi trong ba đối tượng, bạn phải thêm mã ông đề nghị, chỉ chú ý rằng "ORM \" phải được đưa vào trước "ManyToOne" và "JoinColumn". Tôi cũng nói thêm "@var" chú thích chỉ để làm rõ nhiều như posible:

Trong Entity name = "eventsPeopleRoles" của bạn, thêm tài liệu tham khảo của mỗi trong ba đơn vị:

/** 
* @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; 

Trong tên Entity của bạn = "Sự kiện"

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

Trong Entity name = "Person" của bạn

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

Trong Entit của bạn y name = "Vai trò"

/** 
* @var ArrayCollection $eventsPeopleRoles 
* 
* @ORM\OneToMany(targetEntity="EventsPeopleRoles", mappedBy="roles") 
*/ 
private $eventsPeopleRoles; 
+0

Bạn đã phạm sai lầm trong lớp tổ chức sự kiệnPeopleRoles. Thay vì sự kiện riêng tư $; cuối cùng, đó là vai trò $ tư nhân; – kabrice

+0

Cảm ơn Edgar, tôi đã trả lời câu trả lời của mình. – aleph

Các vấn đề liên quan