I ran into a problem with Doctrine ORM’s SoftDeleteble extension a while back and managed to get some time today to finally track down what is happening.
I have a Symfony application with a number of related Doctrine entity classes.
In most cases the parent entity uses cascade={"remove"}
in the association
annotation so Doctrine will remove the children automatically. With the
SoftDelete extenation enabled, this rather elegantly results in the child
entities getting their $deleted_at
property set just like the parent. Very
nice.
The trouble comes when I actually want to delete the parent entity. This came
up in my unit tests where I was trying to clean up entities being persisted. I
have a setUp()
method in the unit test class that disables SoftDelete for the
parent entity and looks for leftovers from previous tests then re-enabled
SoftDelete. It then iterates through the object it found calling remove($obj)
and flush()
twice – once to soft-delete them then again to hard-delete them.
The double-remove logic worked fine until there were leftover child entities. It turns out the first time causes the delete timestamp properties for the parent and children to get set. When the second remove is called, it looks for children but doesn’t find them because they have their deleted field set and they’re hidden. The resulting transaction only includes the parent so the database throws a referential integrity constraint violation error because the child records still reference the parent. I’d need to disable SoftDelete for the children to make this work.
For now, I’ve just removed the SoftDelete extension from the application and will revisit it later.