У меня есть несколько классов, использующих свойство Taggable, чтобы настроить систему тегов, общую для нескольких объектов доктрины (Project, Note, …).
Связь между этими объектами и этими тегами – это отношение ManyToMany, которое я не могу сделать многонаправленным.
Моя проблема: когда я удаляю объект Project, он удаляется из таблицы проекта , но отношения в таблице 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; } }
Taggable
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; } }
-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'); }