mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
Lazy loading OneToMany modifies the owning side #7263
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @FoxCie on GitHub (Nov 29, 2023).
Bug Report
Summary
When fetching a bidirectional OneToMany Collection with lazy fetch mode, all the elements are modified (that is, the property corresponding to the owning side of the element is set to the owner of the Collection).
Current behavior
Owning sides are modified during hydration (lazy-loading).
How to reproduce
Declare a bidirectional OneToMany, modify the owning side, then remove the element (for example) from the older association. The call to
removeElementwill hydrate the Collection, which will set the value of the owning side to its original value (the modification is lost).This bug has been reported several times, at least in #6589, #7932 and probably in #6449 .
Expected behavior
Lazy loading should not modify anything apart from the Collection itself.
Discussion
As stated in some of the previous reports, the bug comes from https://github.com/doctrine/orm/blob/2.17.x/lib/Doctrine/ORM/PersistentCollection.php#L169 .
In the
hydrateAddofPersistentCollection, the owning side is willingly set to the owner :The comment above states that :
If _backRefFieldName is set and its a one-to-many association, we need to set the back reference., but I do not understand why this should happen. Why would hydrating a Collection have anything to do with the owning side? Wouldn't the entity be already populated anyway, either because it was fetched before the call that caused hydration, or because the hydration process already loaded it (since it is being appended to the Collection, it must have been loaded in some way)?In any way this totally breaks the transparent behaviour of lazy-loading, since (as demonstrated by the tests in the other reports linked above) changing the fetch mode to eager for instance solves this issue.
So my question is : is it safe to just remove these lines and not modify the owning side, or are there some side effects that I am not aware of?
From my point of view, if these lines are added to populate a lazy-loaded ManyToOne (the owning side), why not let the lazy-loading process of the owning side happen when require? And if it is not lazy-loaded, then why bother at all, since it must have been loaded previously?