mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
Unable to update belongs-to relationship when loaded through query from the parent (incomplete hydration) #6292
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 @matt-stuart on GitHub (Sep 5, 2019).
Originally assigned to: @matt-stuart on GitHub.
Bug Report
Summary
Symptom: Unable to update the parent of an entity when that entity was loaded via a query from the parent including the children through a join and inclusion in the select list.
Deeper: Hydration of child entities in the UnitOfWork::$originalEntityData during a query that includes the children as part of it does not fully hydrate parent relationships. Specifically, it doesn't hydrate the parent relationship that the child was loaded through.
This causes issues where computing the change set of an entity who was loaded in this way and their parent was changed causes this change to be missed.
From the UnitOfWork.php lines 2686:
Appears to skip hydrating the parent relationship because it's in the hint list
Current behavior
The parent property cannot be changed on the child entities loaded this way as:
The UnitOfWork::$originalEntityData contains a property
parent_id = #as the relationship is not hydrated to the proper fieldparent. When theparentproperty is changed using the entity and persisted no change will be detected as the compute change set won't find the property in the copy coming from $originalEntityDataHow to reproduce
Expected behavior
The parent of the child entity should have changed from the original X to the target Y
@lcobucci commented on GitHub (Sep 5, 2019):
@matt-stuart thanks for submitting the bug report. I'm afraid we need more information than that, for example: which side is the owner of the association? Are you using a different tracking policy (other than the default one)? Have you tried fixing the
Parent#childrenproperty of both parent objects in combination with updating theChildren#parent(as in removing from collection A and appending to collection B)?To clarify everything, could you please send us PR with a failing functional test that fully reproduces the problem?
@matt-stuart commented on GitHub (Sep 5, 2019):
Will do
Update: Tried removing it from the collection, adding it to the new collection, and adjusting the parent pointer. Same behaviour. Adding test.
@matt-stuart commented on GitHub (Sep 5, 2019):
Thought i'd give a quick code sample that's literally what I'm using:
@lcobucci commented on GitHub (Sep 5, 2019):
@matt-stuart since you're changing
$dailyCostand$targetDailyCostand use theDEFERRED_EXPLICITyou must persist them as well (it can be after the loop).@matt-stuart commented on GitHub (Sep 5, 2019):
As a note, through an EventSubscriber ultimately all of the entities get persisted. It's a version tracking thing that updates the treeVersion value on all of the parent entities to ensure tracking tree changes. Either through my ES or through explicit persists in the code above the change to the parent isn't picked up.
When loading these entities through just the relationships instead of through a combined query like above:
the $items get properly updated as they're hydrated fully and the UOW#computeChangeSet can track the change as the internal original record is accurate, this only occurs when hydrating from a join query.
So, that brings the question of who's responsibility of ensuring the internal tracking array is built? UOW has logic that does build out the association properties but are skipped in this case due to the hints provided by the ObjectHydrator class. The ObjectHydrator ALSO has logic that set the UOW#originalEntityData properties when it comes to associations in some cases but it appears not all (see ObjectHydrator#hydrateRowData@~432).
So before I start writing tests, who's responsibility should this be to ensure that the association properties are properly represented in the internal tracking?
@lcobucci commented on GitHub (Sep 5, 2019):
@matt-stuart please send us the PR with the failing test. It will be much simpler to find the problem
@matt-stuart commented on GitHub (Sep 5, 2019):
I'll send one along I'm just wondering what component should be the one considered to be failing. Is it the ObjectHydrator that should be responsible or the UnitOfWork. Both appear to make changes to the UOW::$originalEntityData in some way or another. I'm reviewing the code to determine, what I feel, is the most logical place for this hydration to take place.