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?
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.