orm: No ForeignKeyConstraintViolationException exception when trying to remove an entity

Bug Report

Q A
BC Break kinda
Version 2.15.2

Summary

Since the following change CleanShot 2023-06-03 at 08 04 00@2x Doctrine stopped throwing ForeignKeyConstraintViolationException and (from what I noticed) it removes the entity from the database. What’s more interesting, if we add the deleted lines, and leave the same code at the end of the method – it doesn’t work. So putting this if statement somehow breaks the expected behavior.

Current behavior

No ForeignKeyConstraintViolationException 🤷🏼‍♂️.

How to reproduce

#10753

Expected behavior

ForeignKeyConstraintViolationException should be thrown.

About this issue

  • Original URL
  • State: closed
  • Created a year ago
  • Comments: 20 (17 by maintainers)

Commits related to this issue

Most upvoted comments

A possible fix including documentation updates is in #10763.

#10486 had another side effect: We started to take care of the dirty collections (where to-be-removed entities have been removed), which happens before we reach \Doctrine\ORM\Persisters\Entity\BasicEntityPersister::deleteJoinTableRecords. So, it takes one query per join table row (for every single collection entry), instead of being able to remove all join table rows in a single step per removed entity.

I’ll add query count expectations to \Doctrine\Tests\ORM\Functional\ManyToManyBasicAssociationTest that would have uncovered this.

Well, yes, that’s pretty unambiguous. But.

  • This part of the docs has not seen any relevant changes since the early days of 2.0. We cannot assume that it is “living” documentation, really up to date with the implementation.
  • It suggests the ORM would always make sure the join table is cleaned up. Either this happens in the DB automatically, or the code will run DELETE statements. But, I cannot see in the code where is difference would be made.
  • Assume you have a unidirectional m2m association, let’s stick with the Order *-->* Promotion example. Now, you have a “clean” entity manager, and all you do is to load one Promotion and remove it. How is the EM even supposed to find out about all the potential m2m join tables that might exist, in order to perform this cleanup? Remember, we don’t have a “full” view of all classes that (might) exist, we only know about what we loaded so far and what associations those classes declare. In this example, Promotion does not declare anything (and does not have to!).

@beberlei maybe you have thoughts on that? (sorry for pinging)