我有几个类使用Taggable特质来设置一个标记系统为多个学说实体共同(项目,注意,...)。Symfony Doctrine2 manyToMany关系没有删除 - 具体到SQLite
这些实体与这些标签之间的关系是一种ManyToMany关系,我无法做出多方向的关系。
我的问题:当我删除项目的实体,它是从项目表中删除,但在这个项目和标签之间的project_tag表的关系不会被删除。然后,如果我创建一个新的Project实体,则会引发异常。
An exception exists while executing 'INSERT INTO project_tag (project_id, tag_id) VALUES (?,?)' With params [2, 4]:
SQLSTATE [23000]: Integrity constraint violation: 19 UNIQUE constraint failed: project_tag.project_id, project_tag.tag_id
实体:
标签
/**
* Tag
*
* @ORM\Table(name="tag")
* @ORM\Entity(repositoryClass="AppBundle\Repository\TagRepository")
*/
class Tag
{
/**
* @var int
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, unique=true)
*/
private $name;
/**
* @ORM\Column(name="last_use_at", type="datetime", nullable=false)
* @var \DateTime
*/
private $lastUseAt;
public function __construct()
{
$this->lastUseAt = new \DateTime();
}
public function __toString()
{
return $this->name;
}
/**
* Get id
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* Set name
*
* @param string $name
*
* @return Tag
*/
public function setName($name)
{
$this->name = $name;
return $this;
}
/**
* Get name
*
* @return string
*/
public function getName(): string
{
return $this->name;
}
/**
* @return \DateTime
*/
public function getLastUseAt(): \DateTime
{
return $this->lastUseAt;
}
/**
* @param \DateTime $lastUseAt
*/
public function setLastUseAt(\DateTime $lastUseAt)
{
$this->lastUseAt = $lastUseAt;
}
}
加标签
trait Taggable
{
/**
* @var ArrayCollection
*
* @ORM\ManyToMany(targetEntity="AppBundle\Entity\Tag", cascade={"persist"})
*/
protected $tags;
/**
* Add tag
*
* @param Tag $tag
*
* @return $this
*/
public function addTag(Tag $tag)
{
$tag->setLastUseAt(new \DateTime());
$this->tags[] = $tag;
return $this;
}
/**
* Remove tag
*
* @param Tag $tag
*/
public function removeTag(Tag $tag)
{
$this->tags->removeElement($tag);
}
/**
* Get tags
*
* @return \Doctrine\Common\Collections\Collection
*/
public function getTags()
{
return $this->tags;
}
}
项目
/**
* Project
*
* @ORM\Table(name="project")
* @ORM\Entity(repositoryClass="AppBundle\Repository\ProjectRepository")
*/
class Project
{
use Taggable;
}
备注
class Note
{
use Taggable;
}
这是唯一的解决方案还是我的注释不完整/不正确? 我试着用JoinColumns,JoinTable和onDelete =“cascade”,但没有任何效果。
与此同时,我避开了这个指令放置在抑制之前的问题。
$project->getTags()->clear();
在控制器的动作全码:
/**
* @Route("/project/{id}/delete", name="project_delete")
*/
public function deleteAction($id) {
$em = $this->getDoctrine()->getManager();
$project = $em->getRepository('AppBundle:Project')->find($id);
if(!$project) {
return $this->redirectToRoute('index');
}
$project->getTags()->clear();
$em->remove($project);
$em->flush();
return $this->redirectToRoute('index');
}
值得注意的是,这个解决方案特定于sqlite,如您在下面的评论中所建议的。 – ehymel
也许更好的办法是使用Doctrine的[preFlush](http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/events.html#preflush)事件([Symfony's事件订户](http://symfony.com/doc/current/doctrine/event_listeners_subscribers.html))。因为它会阻止在没有执行写入查询的页面上执行命令。 – naitsirch