【发布时间】:2014-04-27 12:30:41
【问题描述】:
目标是拥有 2 个实体文章和标签,具有多对多关系,其中标签表中的标签保持唯一,即使为其他文章声明相同的标签。 我尝试用代码更好地解释:
文章实体:
/**
* @ORM\Entity
* @ORM\Table(name="articles")
*/
class Article {
/**
* @ORM\Id @ORM\GeneratedValue(strategy="AUTO") @ORM\Column(type="integer")
* @var int
*/
protected $id;
/**
* @ORM\Column(type="string")
* @var string
*/
protected $name;
/**
* @ORM\ManyToMany(targetEntity="Tag\Entity\Tag",inversedBy="platforms",cascade={"persist","remove"})
*
* @return Tag[]
*/
protected $tags;
public function __construct() {
$this->tags = new ArrayCollection();
}
public function setId($id) {
$this->id = $id;
}
public function getId() {
return $this->id;
}
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
public function setTags($tags){
$this->tags = $tags;
}
public function setTagsFromArray(array $tags){
foreach($tags as $tag){
$this->tags->add(new Tag($tag));
}
}
/**
* Return the associated Tags
*
* @param boolean $getOnlyTagsName [optional] If set to true return a simple array of string (tags name).
* If set to false return array of Tag objects.
*
* @return Tag[]|string[]
*/
public function getTags($getOnlyTagsName=false) {
if ($getOnlyTagsName){
return array_map(function($i) { return $i->getName(); }, $this->tags->toArray());
}
return $this->tags;
}
public function addTags($tags) {
foreach($tags as $tag){
$this->tags->add($tag);
}
}
public function removeTags($tags) {
foreach ($tags as $tag){
$this->tags->removeElement($tag);
}
}
}
标记实体:
/**
* @ORM\Entity
* @ORM\Table(name="tags")
* ORM\HasLifecycleCallbacks // NOT USED
*/
class Tag {
/**
* @ORM\Id @ORM\Column(type="integer") @ORM\GeneratedValue
* @var int
*/
protected $id;
/**
* @ORM\Column(type="string",unique=true)
* @var string
*/
protected $name;
/**
* @ORM\Column(type="datetime",name="created_at")
* @var datetime
*/
protected $createdAt;
/**
* @ORM\Column(type="datetime",name="updated_at")
* @var datetime
*/
protected $updatedAt;
/**
* @ORM\ManyToMany(targetEntity="Article\Entity\Article", mappedBy="tags")
* var Tag[]
*/
protected $platforms;
/**
* Constructor
*
* @param string $name Tag's name
*/
public function __construct($name = null) {
$this->setName($name);
$this->setCreatedAt(new DateTime('now'));
$this->setUpdatedAt(new DateTime('now'));
}
/**
* Avoid duplicate entries.
*
* ORM\PrePersist // NOT USED
*/
public function onPrePersist(LifecycleEventArgs $args) {
}
/**
* Avoid duplicate entries.
*
* ORM\PreUpdate // NOT USED
*/
public function onPreUpdate(PreUpdateEventArgs $args) {
}
public function setId($id) {
$this->id = $id;
}
/**
* Returns tag's id
*
* @return integer
*/
public function getId() {
return $this->id;
}
/**
* Sets the tag's name
*
* @param string $name Name to set
*/
public function setName($name) {
$this->name = $name;
}
/**
* Returns tag's name
*
* @return string
*/
public function getName() {
return $this->name;
}
public function setCreatedAt(DateTime $date) {
$this->createdAt = $date;
}
public function getCreatedAt() {
return $this->createdAt;
}
public function setUpdatedAt(DateTime $date) {
$this->updatedAt = $date;
}
public function getUpdatedAt() {
return $this->updatedAt;
}
}
然后我有文章表单(带有文章字段集),其中有一个 tagsinput(jquery 插件)元素。所以表单发布是这样的:
object(Zend\Stdlib\Parameters)[151]
public 'security' => string 'dc2a6ff900fbc87933e07bd35ef36709...' (length=65)
public 'article' =>
array (size=3)
'id' => string '' (length=0)
'name' => string 'Article 1' (length=13)
'tags' =>
array (size=3)
0 => string 'tag1' (length=3)
1 => string 'tag2' (length=4)
2 => string 'tag3' (length=7)
public 'submit' => string 'Add' (length=8)
第一次插入一切顺利,但是当我尝试使用 article1 标记之一插入另一篇文章时,我收到错误:
An exception occurred while executing 'INSERT INTO tags (name, created_at, updated_at) VALUES (?, ?, ?)' with params ["tag2", "2014-04-26 22:05:37", "2014-04-26 22:05:37"]:
SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'tag2' for key 'UNIQ_6FBC94265E237E06'
我知道我可以使用 prePersist 和 preUpdate 事件监听器,但是我做了一些测试,但我不知道如何使用 Unit Of Work 来避免重复。
【问题讨论】:
标签: orm doctrine-orm zend-framework2 many-to-many duplicates