mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
Change default tracking policy for "deferred explicit" #7515
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 @Pierstoval on GitHub (Jun 2, 2025).
Current default Tracking policy is set to "deferred implicit", has been since the beginning, meaning all objects retrieved from repositories are stored in the UnitOfWork for potential updates/deletions for the next call to em->flush or uow->commit
However, I stopped counting the amount of Symfony+Doctrine projects I worked on that suffered from that on two specific levels:
$em->flush()will trigger all the cascading checks for entities updates and deletionsWhenever we encounter performance issues for that, the usual solution is to run the updates in batches, but even then, sometimes you have a batch of entities on which only a percentage need to be actually updated, meaning we lose performances on all other changesets checks and comparisons.
And for the side-effects, I blame the default anemic-objects behavior that most documentations have been recommending for years, because updates on anemic entities can happen anywhere without validation, and the main place I found these were when Symfony Forms were used with Doctrine Entities.
Even though Symfony Forms trigger validation on submit to ensure "one will not persist it", a big bunch of legacy apps still use kernel or doctrine events for other kinds of usages that might call a
flush()somewhere.It can definitely happen in 3rd-party libs, even though the most popular ones usually take care, but we're never sure, will never be, and all the legacy apps in the world using the old-recommended event-based coding practice will encounter this some day. Even EasyAdmin forgot to call "persist()" on update at some point, meaning the whole "Doctrine persists by default" is deeply anchored to devs' minds, even the ones of the most talented and active in the Symfony ecosystem.
Changing the default tracking policy in a major version, and adding a migration path (i.e "A deprecation message recommending to set the annotation manually on each entity", maybe followed by some static analysers, hopefully) will help devs understand more how Doctrine works, and if they decide to keep the "implicit" behavior, they will know what to expect, especially if they migrated using Rector or similar tools that enforce them to explicitly define the PHP attribute to configure the tracking policy.
Conjointedly, the policy could be configurable directly in the
Entityannotation in a minor version instead of having its own attribute, to help for better discovery, curiosity and understanding of this concept.Of course this sounds like a big change, but it's quite as big as the removal of single-entity flush, or removal of the "notify" strategy in ORM v4, for example, but if this is ever accepted at some point, I'm willing to help working on it, since I've been promoting this for a long time.
@greg0ire commented on GitHub (Jun 4, 2025):
Hi and thanks for the detailed issue!
This sounds a bit scary… how about instead we somehow, if possible, make the tracking policy configurable on an application per application basis in a minor release, and then, if more people feel it should be the default, change the symfony recipe to configure it to deferred explicit. This way, we could get feedback on this change without affecting existing applications. We could then configure changing or even removing the default value.
@beberlei commented on GitHub (Jun 5, 2025):
I doubt this will happen, its too big a change. Single entity flush and notify policy removal did not require adding code, it would mostly just continue to work.
Your proposal would require to ausir code for adding persist at the right places and that could be daunting.
@Pierstoval commented on GitHub (Jun 11, 2025):
I've seen projects migrating from this having a huge lot of issues because they relied on single entity flushes a lot, which triggered architectural changes in the app itself. This happens.
Yep, this seems like a good migration path! A message saying
doctrine.orm.entity_managers.default: not specifying the "default_tracking_policy" option is deprecated, it is currently set to "deferred_implicit" and will default to "deferred_explicit" in version X, updating the default recipe to contain thedeferred_implicitvalue with a link to the Doctrine ORM docs about tracking policies, and setting it todeferred_explicitin a next-gen recipe would help both discovering AND documenting said option.