mirror of
https://github.com/doctrine/orm.git
synced 2026-03-23 22:42:18 +01:00
[PR #12174] [MERGED] Do not eagerly set metadata from ResolveTargetEntityListener
#13541
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?
📋 Pull Request Information
Original PR: https://github.com/doctrine/orm/pull/12174
Author: @mpdude
Created: 9/19/2025
Status: ✅ Merged
Merged: 10/15/2025
Merged by: @greg0ire
Base:
2.20.x← Head:resolve-target-entity-listener-no-eager-metadata📝 Commits (2)
8c6ae83Do not eagerly set metadata from ResolveTargetEntityListener859bb25Rename test method for clarity📊 Changes
3 files changed (+96 additions, -12 deletions)
View changed files
📝
phpstan-baseline.neon(+0 -6)📝
src/Tools/ResolveTargetEntityListener.php(+0 -6)➕
tests/Tests/ORM/Functional/Ticket/GH12174Test.php(+96 -0)📄 Description
When using the
ResolveTargetEntityListenerto substitutetargetEntitiesin association mappings, do not eagerly put the resolved (target) entity into the class metadata cache under the class name of the original entity.Motivation
I have a library that wants to distribute a MappedSuperclass as the base for some functionality. It will be necessary that clients using the library will extend the MappedSuperclass to fill in some blanks, creating the first real
#[Entity]instance of it.This client-provided entity will be the primary means of working with the class. Thus, I was following the note in the documentation and using the
ResolveTargetEntityListenerto declare that whenever an association refers to that mapped superclass, the particular entity class shall be used instead.Changes made
The
ResolveTargetEntityListenerprimarily does what its name suggests: For newly loaded class metadata, it inspects all associations declared and replaces thetargetEntitywith new (resolved) values.But additionally, when a loaded class is the target of such a resolution, it would also put the class metadata into the cache under the name of the original entity.
I think that extra step is wrong, and this PR removes it. It had the side effect that when other classes extending the MappedSuperclass were loaded after the resolve target class has been seen for the first time, the metadata for those classes would not inherit from the mapped superclass anymore, but from the target entity class instead. In my real-life use case, this causes weird mapping errors down the road; as of ^3.0, it would throw a mapping exception asking to configure inheritance mapping. But note that there would be no inheritance between the entity classes at all.
More background
The documentation describes the use of
ResolveTargetEntityListenerwith an interface that is resolved to an entity class. For an interface, adding the extra metadata does not make a difference, since it never interferes with actual entity or mapped superclasses.The initial idea of adding a copy of the entity class metadata under the interface name came from commit
9c7f3f2747in #385. The goal was to make it possible to also find entities by interface names, like so:It then turned out that this only worked when the resolution had already been applied. So, the new
onClassMetadataNotFoundevent was added and the resolution map would be checked in that case as well (#1181). The inital code stayed in place, possibly giving a small performance gain.🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.