Связь базы данных Symfony2 / Doctrine2 между группой, сообщением и местоположением

Я пытаюсь найти правильную модель отношений между группой пользователей, коротким отображаемым предупреждающим сообщением и именованным местоположением.

Например: студенты и стажеры (группы) может понадобиться специальная инструкция (Сообщение) для отображения в верхней части страницы (Место нахождения), в то время как учителям и руководителям команд может понадобиться увидеть другую строку текста.

  • Местоположение может иметь несколько сообщений, но только одно на группу.
  • Группа может иметь несколько сообщений, но только одно для каждого местоположения.
  • Несколько групп (тысячи, в некоторых случаях) могут быть назначены одному и тому же сообщению, поэтому Сообщение как объект с ключами к местоположению & группа вызовет много дублирования.
class Message {

/**
* @ORM\ManyToOne(targetEntity="...Bundle\Entity\Group", inversedBy="messages")
* @ORM\JoinColumn(name="group_id", referencedColumnName="id", nullable=false)
*/
protected $groups;

/**
* @ORM\ManyToOne(targetEntity="...Bundle\Entity\Location", inversedBy="messages")
* @ORM\JoinColumn(name="location_id", referencedColumnName="id", nullable=false)
*/
protected $location;
}

Я чувствую, что должно быть отношение «многие к одному» между сообщениями и местоположением, и отношение «многие к одному» между группами и какой-либо объединенной сущностью «сообщение + местоположение».

У меня проблемы с настройкой сущностей таким способом.

0

Решение

С вашей схемой вы можете сделать что-то вроде этого:

class Message {

/**
* @ORM\ManyToMany(targetEntity="...Bundle\Entity\Group", inversedBy="messages")
* @ORM\JoinColumn(name="group_message"* joinColumns={@ORM\JoinColumn(name="group_id", referencedColumnName="id")},
* inverseJoinColumns={@ORM\JoinColumn(name="message_id", referencedColumnName="id")})

*/
protected $groups; //Here, a group can have many messages and a messages can be attached at many groups so => manyToMany

/**
* @ORM\ManyToOne(targetEntity="...Bundle\Entity\Location", inversedBy="messages")
* @ORM\JoinColumn(name="location_id", referencedColumnName="id", nullable=false)
*/
protected $location; //[1] Message can have One location and location can have many messages in the case of messages at the same location are not assigned at the same group.
}

class Location {

/**
* @ORM\OneToMany(targetEntity="...Bundle\Entity\Message", mappedBy="location")
* @ORM\JoinColumn(name="message_id", referencedColumnName="id", nullable=false)
*/
protected $messages;

}

class Group {

/**
* @ORM\ManyToMany(targetEntity="...Bundle\Entity\Message", mappedBy="groups")
*/
protected $messages;

}

Чтобы обеспечить условие [1], вы можете сделать обратный вызов в вашем Message юридическое лицо. Этот обратный вызов будет проверять, когда вы вставляете сообщение, что у группы нет другого сообщения в том же месте.

Чтобы сделать обратный звонок, здесь документ:

/**
* @Assert\Callback({"Vendor\Package\Validator", "validate"})
*/
class Message {
[...]
public function validate(ExecutionContextInterface $context)
{

// check if the location is already used for one of the group on $this (entity returned by the form)
foreach($this->getGroups() as $group) {

foreach($group->getMessages as $message) {

if ($this->getLocation() == $message->getLocation()) {

$context->buildViolation('Location already used!')
->atPath('location')
->addViolation();
}
}
}
// If you're using the old 2.4 validation API
/*
$context->addViolationAt(
'location',
'Location already used!'
);
*/
}
}
}
1

Другие решения

Других решений пока нет …