mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
Cannot override the class metadata factory via configuration since 3.0 #7382
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 @alekitto on GitHub (Jun 12, 2024).
Bug Report
Summary
Since version 3.0.0, the class metadata factory cannot be overridden.
Previous behavior
The entity manager has been instantiated taking the class name from the configuration on entity manager construction
Current behavior
Since
ea97ea4c47the override is broken as the entity manager is wired to the classDoctrine\ORM\Mapping\ClassMetadataFactory.To allow overriding via configuration, it should be wired against
Doctrine\Persistence\Mapping\ClassMetadataFactoryinterface.How to reproduce
This is the same exact bug reported on mongodb-odm at https://github.com/doctrine/mongodb-odm/issues/2551
The only difference is that on mongodb-odm this was considered a BC break, as the bug was introduced in a minor version.
@derrabus commented on GitHub (Jun 12, 2024):
Obviously not a bug. Please elaborate your use-case.
@alekitto commented on GitHub (Jun 12, 2024):
As explained also in the ODM issue:
I used this feature in 2.x without any problem, but defining the concrete type into the EntityManager does not allow to use any other class implementing the common interface/extending the abstract class.
@derrabus commented on GitHub (Jun 12, 2024):
You did not answer the question.
@alekitto commented on GitHub (Jun 12, 2024):
Yes, I did. My use-case is to create a fake/mock version of the class metadata factory implementing
Doctrine\Persistence\Mapping\ClassMetadataFactoryinterface, and using it in testing to control what is returned from the factory itself and when the factory methods are called.In the current state calling
setClassMetadataFactoryNameon configuration with such a class results in a fatal error on entity manager construction. But the same thing was possible in 2.x because the property type was not defined, so it was possible to implement the interface/extend the abstract class to have your custom implementation of the class metadata factory.What else do you need to know precisely?
@derrabus commented on GitHub (Jun 12, 2024):
As far as I know, our factory is not final, so you may still mock it.
@alekitto commented on GitHub (Jun 12, 2024):
The class itself is not final, but some of the public methods are final in
ClassMetadataFactoryand inAbstractClassMetadataFactoryand cannot be overridden (also what's the purpose of the abstract class if cannot be used in the entity manager?) .I'm currently replacing the class completely, just implementing the interface.
@derrabus commented on GitHub (Jun 12, 2024):
I see. Well, we could introduce a new interface for our factory that you can mock. Please send a PR.
@alekitto commented on GitHub (Jun 12, 2024):
👍 Ok, thanks. I'll send it tomorrow.
@SenseException commented on GitHub (Aug 5, 2024):
I was wondering about the interface introduced in #11497. It seems that it contains the rest of the public methods that were added to the
Doctrine\ORM\Mapping\ClassMetadataFactoryas the "rest" that isn't provided by Doctrine Persistence. There isgetOwningSide(), a setter for an EntityManager and a Cache setter forPsr\Cache\CacheItemPoolInterfaceinstances. These seem to be different responsibilities for just putting then into one interface. Setting a Cache happens in Persistence while the EntityManager is in ORM. I wonder if those can be split up so that ORM doesn't get an interface where everything else is put into.@alekitto commented on GitHub (Aug 5, 2024):
@SenseException I agree with your objections, but the same applies to the
ClassMetadataFactoryclass.The meaning of that interface is to create a minimum set of methods used by the ORM that needs to be implemented in order to override the metadata factory.
I don't know if this could be split easily; maybe the setters could be avoided passing them to the factory constructor, but in this case you can't just customise the factory class name in configuration, but you need to set into the configuration object at least a closure that creates the factory.