Symfony2/Doctrine2群组、消息和位置之间的数据库关系
Symfony2/Doctrine2 database relationship between a group, a message and a location
我正在尝试为一组用户、显示的简短警报消息和命名位置之间的关系提出正确的模型。
例如:学生和实习生 (Groups) 可能需要特殊说明 (Message)页面(位置),而教师和团队经理可能需要查看不同的文本字符串。
- 一个位置可以有多条消息,但每组只能一条消息。
- 一个群组可以有多条消息,但每个位置只能有一条消息。
- 可以为多个组(在某些情况下为数千个)分配相同的相同消息,因此消息作为具有位置和组键的实体会导致大量重复。
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;
}
我觉得 Messages 和 Location 之间应该有多对一的关系,组和一些组合的 "Message+Location" 实体之间应该有多对一的关系。
不过,我在以这种方式设置实体时遇到了问题。
使用您的模式,您可以做类似的事情:
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
实体中进行回调。当您插入消息时,此回调将检查群组在同一位置没有另一条消息。
要进行回调,here the doc is:
/**
* @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!'
);
*/
}
}
}
我正在尝试为一组用户、显示的简短警报消息和命名位置之间的关系提出正确的模型。
例如:学生和实习生 (Groups) 可能需要特殊说明 (Message)页面(位置),而教师和团队经理可能需要查看不同的文本字符串。
- 一个位置可以有多条消息,但每组只能一条消息。
- 一个群组可以有多条消息,但每个位置只能有一条消息。
- 可以为多个组(在某些情况下为数千个)分配相同的相同消息,因此消息作为具有位置和组键的实体会导致大量重复。
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;
}
我觉得 Messages 和 Location 之间应该有多对一的关系,组和一些组合的 "Message+Location" 实体之间应该有多对一的关系。
不过,我在以这种方式设置实体时遇到了问题。
使用您的模式,您可以做类似的事情:
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
实体中进行回调。当您插入消息时,此回调将检查群组在同一位置没有另一条消息。
要进行回调,here the doc is:
/**
* @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!'
);
*/
}
}
}