DDC-3344: Flush on a specific entity is not correctly cascaded to associated entities #4132

Closed
opened 2026-01-22 14:35:46 +01:00 by admin · 11 comments
Owner

Originally created by @doctrinebot on GitHub (Oct 10, 2014).

Originally assigned to: @Majkl578 on GitHub.

Jira issue originally created by user pavel.horal:

In a setup with a simple entity associated entity, the cascade is not performed when flushing the parent entity. This violates contract specified by EntityManager#flush($entity) PHPDoc:

bq. If an entity is explicitly passed to this method only this entity and the cascade-persist semantics + scheduled inserts/removals are synchronized.

It seems that the reason behind this is UnitOfWork#computeAssociationChanges, which expects that a #computeChangeSets is called elswehere (which it is not when flushing a specific entity):

bq. MANAGED associated entities are already taken into account during changeset calculation anyway, since they are in the identity map.

This makes flushing and cascading very confusing. Also I believe this might be a cause of other issues, like DDC-3113.

Originally created by @doctrinebot on GitHub (Oct 10, 2014). Originally assigned to: @Majkl578 on GitHub. Jira issue originally created by user pavel.horal: In a setup with a simple entity associated entity, the cascade is not performed when flushing the parent entity. This violates contract specified by [`EntityManager#flush($entity)` PHPDoc](https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/EntityManager.php#L342-L343): bq. If an entity is explicitly passed to this method only this entity and the cascade-persist semantics + scheduled inserts/removals are synchronized. It seems that the reason behind this is [`UnitOfWork#computeAssociationChanges`](https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php#L845-L846), which expects that a `#computeChangeSets` is called elswehere (which **it is not** when flushing a specific entity): bq. MANAGED associated entities are already taken into account during changeset calculation anyway, since they are in the identity map. This makes flushing and cascading very confusing. Also I believe this might be a cause of other issues, like [DDC-3113](http://www.doctrine-project.org/jira/browse/DDC-3113).
admin added the BugWon't Fix labels 2026-01-22 14:35:46 +01:00
admin closed this issue 2026-01-22 14:35:47 +01:00
Author
Owner

@doctrinebot commented on GitHub (Oct 10, 2014):

Comment created by @ocramius:

Doctrine\ORM\EntityManager#flush() is not supposed to be called with a specific entity when there are cascade operations involved.

The optional argument has to be only used for performance reasons, but can indeed break things.

@doctrinebot commented on GitHub (Oct 10, 2014): Comment created by @ocramius: `Doctrine\ORM\EntityManager#flush()` is not supposed to be called with a specific entity when there are cascade operations involved. The optional argument has to be only used for performance reasons, but can indeed break things.
Author
Owner

@doctrinebot commented on GitHub (Oct 10, 2014):

Comment created by pavel.horal:

Thank you for the reply. I am probably (and possibly other people) misinterpretting the PHPDoc. Can you explain what is meant by "and the cascade-persist semantics"?

@doctrinebot commented on GitHub (Oct 10, 2014): Comment created by pavel.horal: Thank you for the reply. I am probably (and possibly other people) misinterpretting the PHPDoc. Can you explain what is meant by _"and the cascade-persist semantics"_?
Author
Owner

@doctrinebot commented on GitHub (Oct 19, 2014):

Comment created by @ocramius:

[pavel.horal] I don't really understand that bit myself, but git blame states that the comment was introduced in 5d3298e706 by [beberlei].

Maybe it just needs a docblock rewrite

@doctrinebot commented on GitHub (Oct 19, 2014): Comment created by @ocramius: [<sub>pavel.horal] I don't really understand that bit myself, but git blame states that the comment was introduced in https://github.com/doctrine/doctrine2/commit/5d3298e706b1457ca8be02469b00ef219afe84e6 by [</sub>beberlei]. Maybe it just needs a docblock rewrite
Author
Owner

@doctrinebot commented on GitHub (Oct 19, 2014):

Comment created by pavel.horal:

Commit is linked with DDC-720 . Again, that gives me an impression that events should be cascaded:

bq. In a nutshell, this change would mean that flush() can optionally accept an entity as an argument. When that happens, the resulting changeset will be limited to that entity and any entity reachable from it.

@doctrinebot commented on GitHub (Oct 19, 2014): Comment created by pavel.horal: Commit is linked with [DDC-720](http://www.doctrine-project.org/jira/browse/DDC-720) . Again, that gives me an impression that events should be cascaded: bq. In a nutshell, this change would mean that flush() can optionally accept an entity as an argument. When that happens, the resulting changeset will be limited to that entity and any entity reachable from it.
Author
Owner

@doctrinebot commented on GitHub (Oct 19, 2014):

Comment created by @ocramius:

{quote}Again, that gives me an impression that events should be cascaded{quote}

No, the entire flush($entity) functionality is just to limit the entire Doctrine\ORM\UnitOfWork operations over the single object: it's expected behavior.

In general, you should use flush($entity) only if you have very high priority performance optimizations, as it was never meant to be reliable API when using listeners.

I'd even suggest deprecating it for removal in the next major release, as it has only caused issues so far.

@doctrinebot commented on GitHub (Oct 19, 2014): Comment created by @ocramius: {quote}Again, that gives me an impression that events should be cascaded{quote} No, the entire `flush($entity)` functionality is just to limit the entire `Doctrine\ORM\UnitOfWork` operations over the single object: it's expected behavior. In general, you should use `flush($entity)` only if you have very high priority performance optimizations, as it was never meant to be reliable API when using listeners. I'd even suggest deprecating it for removal in the next major release, as it has only caused issues so far.
Author
Owner

@doctrinebot commented on GitHub (May 31, 2015):

Comment created by jkleijn:

I also ran into this. I foolishly made the assumption that flush($entity) was intended to flush an entity and all associations (following "persist" cascade rules).

Intended or not, I firmly believe this should be the default behavior (or create a second set of cascade rules, eg "flush"). The reasoning behind it is one of encapsulation. Client code calling flush() cannot know what is flushed unless it owns all entity interaction, which is both undesirable and unrealistic. A single service may very well own all interactions on a specific object and its associations though.

@doctrinebot commented on GitHub (May 31, 2015): Comment created by jkleijn: I also ran into this. I foolishly made the assumption that flush($entity) was intended to flush an entity and all associations (following "persist" cascade rules). Intended or not, I firmly believe this should be the default behavior (or create a second set of cascade rules, eg "flush"). The reasoning behind it is one of encapsulation. Client code calling flush() cannot know what is flushed unless it owns all entity interaction, which is both undesirable and unrealistic. A single service may very well own all interactions on a specific object and its associations though.
Author
Owner

@dave-newson commented on GitHub (Nov 16, 2016):

Just tripped over this with an entire team of people, then found this bug report.

What's the intended fix for this bug? Options appear to be:

  • Deprecate the specific entity flush capability in future versions
  • Make EntityManager#flush($entity) perform cascade persist options on $entity when it's provided
  • Remove the misleading PhpDoc block
@dave-newson commented on GitHub (Nov 16, 2016): Just tripped over this with an entire team of people, then found this bug report. What's the intended fix for this bug? Options appear to be: - Deprecate the specific entity flush capability in future versions - Make `EntityManager#flush($entity)` perform cascade persist options on `$entity` when it's provided - Remove the misleading PhpDoc block
Author
Owner

@lcobucci commented on GitHub (Nov 16, 2016):

@dave-newson #6118

@lcobucci commented on GitHub (Nov 16, 2016): @dave-newson #6118
Author
Owner

@El-Sam commented on GitHub (Sep 14, 2017):

I just had the same issue as @dave-newson.

Is there any updates on this issue.

@El-Sam commented on GitHub (Sep 14, 2017): I just had the same issue as @dave-newson. Is there any updates on this issue.
Author
Owner

@lcobucci commented on GitHub (Oct 8, 2017):

@El-Sam as mentioned on https://github.com/doctrine/doctrine2/issues/4142#issuecomment-260860879 we already removed the feature on v3. So to make it short, don't pass any parameter to EntityManager#flush().

@lcobucci commented on GitHub (Oct 8, 2017): @El-Sam as mentioned on https://github.com/doctrine/doctrine2/issues/4142#issuecomment-260860879 we already removed the feature on v3. So to make it short, don't pass any parameter to `EntityManager#flush()`.
Author
Owner

@Majkl578 commented on GitHub (Dec 19, 2017):

Closing, flushing specific entities is going to be removed in Doctrine 3.0.

@Majkl578 commented on GitHub (Dec 19, 2017): Closing, flushing specific entities is going to be removed in Doctrine 3.0.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#4132