Skip to content

Fix flush crash when deleting an inherited ManyToMany target (#105)#106

Merged
rcsofttech85 merged 1 commit into
rcsofttech85:mainfrom
gdbonino:fix/manytomany-inheritance-criteria
Jun 13, 2026
Merged

Fix flush crash when deleting an inherited ManyToMany target (#105)#106
rcsofttech85 merged 1 commit into
rcsofttech85:mainfrom
gdbonino:fix/manytomany-inheritance-criteria

Conversation

@gdbonino

Copy link
Copy Markdown
Contributor

Fixes #105.

Problem

Deleting an entity that is the target of a ManyToMany association whose target class uses class inheritance (JOINED / SINGLE_TABLE) crashes during EntityManager::flush():

ResultSetMappingBuilder does not currently support your inheritance scheme.
(InvalidArgumentException)

AssociationImpactAnalyzer::canReadCollectionThroughCriteria() returns true for any clean, uninitialized PersistentCollection, so resolveCollectionItems() / resolveCollectionIds() read the owner collection via matching(Criteria::create()). Doctrine's ManyToManyPersister::loadCriteria() builds a ResultSetMapping through ResultSetMappingBuilder::addRootEntityFromClassMetadata(), which explicitly rejects inheritance schemes — a long-standing Doctrine limitation, so the bundle can't rely on matching() for those associations.

Fix

Skip the Criteria fast-path when the association is ManyToMany and the target entity uses inheritance, falling back to the existing iteration / lazy-loading path (which hydrates inherited entities correctly):

private function canReadCollectionThroughCriteria(PersistentCollection $items): bool
{
    if ($items->getMapping()->isManyToMany() && !$items->getTypeClass()->isInheritanceTypeNone()) {
        return false;
    }

    return !$items->isInitialized() && !$items->isDirty();
}

This is a behavior fix only — no public API change.

Test

Adds a functional regression test (ManyToManyInheritanceDeleteTest) with a new fixture (Club → ManyToMany → inherited Membership / PremiumMembership, JOINED). It mirrors the existing CollectionInitializationSafetyTest delete-impact scenario but with an inherited target: it deletes a membership while the owner collection is clean and uninitialized, and asserts the flush no longer crashes and the owner audit log records the 5 → 4 change. The test fails on main with the exact ResultSetMappingBuilder error and passes with the fix.

composer check is green (921 tests, PHPStan, php-cs-fixer).

…ech85#105)

Deleting an entity that is the target of a ManyToMany association whose
target class uses inheritance (JOINED/SINGLE_TABLE) crashed during
EntityManager::flush() with:

    ResultSetMappingBuilder does not currently support your inheritance scheme.

AssociationImpactAnalyzer::canReadCollectionThroughCriteria() returned true
for any clean, uninitialized PersistentCollection, so resolveCollectionItems()
/ resolveCollectionIds() read the owner collection via matching(Criteria).
Doctrine's ManyToManyPersister::loadCriteria() builds a ResultSetMapping via
ResultSetMappingBuilder::addRootEntityFromClassMetadata(), which explicitly
rejects inheritance schemes.

Bail out of the Criteria fast-path when the association is ManyToMany and the
target entity uses inheritance, falling back to the existing iteration / lazy
loading path, which hydrates inherited entities correctly.

Adds a functional regression test (Club -> ManyToMany -> inherited Membership)
that crashes on flush without the fix.

Fixes rcsofttech85#105

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codacy-production

Copy link
Copy Markdown

Up to standards ✅

🟢 Issues 0 issues

Results:
0 new issues

View in Codacy

🟢 Metrics 0 complexity · 0 duplication

Metric Results
Complexity 0
Duplication 0

View in Codacy

NEW Get contextual insights on your PRs based on Codacy's metrics, along with PR and Jira context, without leaving GitHub. Enable AI reviewer
TIP This summary will be updated as you push new changes.

@rcsofttech85 rcsofttech85 merged commit b4e9105 into rcsofttech85:main Jun 13, 2026
12 checks passed
@rcsofttech85

Copy link
Copy Markdown
Owner

Thank You @gdbonino

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

flush() crashes when deleting an entity whose ManyToMany target uses class inheritance (matching() / Criteria unsupported)

2 participants