deleting entities in cascade not working in ManyTo

2019-02-07 05:40发布

问题:

I have a parent entity Category and a child entity Article. They are defined by a ManyToMany relation. One article can be taged in one or more category and every Category can be tagged in more than one Article.

WHAT I TRY TO DO
I would like that when I delete a Category, every Article tagged in the Category are also deleted BUT only if they are not tagged by an other Category.

WHAT I HAVE ALREADY TESTED
I tested with 2 category (id=1 and id=2) and with two articles (id=71 and id=91). article 71 has both category 1 and 2. Article 91 is linked only with category 2.
So when deleting category 2 I expect to delete article 91 but not article 71 (as this one is still linked with category_1)

But none of this happenned whatever I tried...

In the following picture I summed up what I get using different strategies (1/cascade={"remove"} , 2/orphanRemoval=true and 3/ondelete="CASCADE" ).
In green the removal from the database.

MY CODE (PART OF CODE)

in the controller

public function deleteCategory(Category $category)
{
  $em = $this->getDoctrine()->getManager();
  $em->remove($category);
  $em->flush();
}

for strategy 1/ cascade={"remove"}

 // IN CLASS/ENTITY CATEGORY - OWNER OF THE RELATION
 * @ORM\ManyToMany(targetEntity="Article", inversedBy="categories",  cascade={ "remove"})
 private $articles;

 // IN CLASS/ENTITY ARTICLE 
 * @ORM\ManyToMany(targetEntity="Category", mappedBy="articles")
 private $categories;

for strategy 2/ orphanRemoval=true

 // IN CLASS/ENTITY CATEGORY - OWNER OF THE RELATION
 * @ORM\ManyToMany(targetEntity="Article", inversedBy="categories",  orphanRemoval=true)
 private $articles;

 // IN CLASS/ENTITY ARTICLE 
 * @ORM\ManyToMany(targetEntity="Category", mappedBy="articles")
 private $categories;

for strategy 3/ onDelete="CASCADE"

 // IN CLASS/ENTITY CATEGORY - OWNER OF THE RELATION
 * @ORM\ManyToMany(targetEntity="Article", inversedBy="categories")
 private $articles;

 // IN CLASS/ENTITY ARTICLE 
 * @ORM\ManyToMany(targetEntity="Category", mappedBy="articles")
 * @ORM\JoinColumn(onDelete="CASCADE")

 private $categories;

MY QUESTION

is there some other way of doing it but the 3 strategies I already tried or those removals have to be done in the controller?

回答1:

You can't do this using just cascading features as far as I can think of.

A clean solution would be to create an listener which subscribes to the preRemove events. You can then check when a category is deleted and find all articles from that category which do not have any other categories and remove those as well.