Switch proxies to LazyGhostTrait#2700
Conversation
9bdb39c to
a81c08c
Compare
LazyGhostTraitLazyGhostTrait
| use function substr; | ||
|
|
||
| /** @internal */ | ||
| class LazyGhostProxyClassNameResolver implements ClassNameResolver, ProxyClassNameResolver |
There was a problem hiding this comment.
This class is copied from Doctrine\ORM\Proxy\DefaultProxyClassNameResolver.
| * @template T of object | ||
| * @template-extends Proxy<T> | ||
| */ | ||
| interface InternalProxy extends Proxy |
There was a problem hiding this comment.
This interface is copied from Doctrine\ORM\Proxy\InternalProxy.
| $proxyManagerConfiguration = new ProxyManagerConfiguration(); | ||
| $proxyManagerConfiguration->setProxiesTargetDir($this->getProxyDir()); | ||
| $proxyManagerConfiguration->setProxiesNamespace($this->getProxyNamespace()); | ||
|
|
||
| switch ($this->getAutoGenerateProxyClasses()) { | ||
| case self::AUTOGENERATE_FILE_NOT_EXISTS: | ||
| $proxyManagerConfiguration->setGeneratorStrategy(new FileWriterGeneratorStrategy( | ||
| new FileLocator($proxyManagerConfiguration->getProxiesTargetDir()), | ||
| )); | ||
|
|
||
| break; | ||
| case self::AUTOGENERATE_EVAL: | ||
| $proxyManagerConfiguration->setGeneratorStrategy(new EvaluatingGeneratorStrategy()); | ||
|
|
||
| break; | ||
| default: | ||
| throw new InvalidArgumentException('Invalid proxy generation strategy given - only AUTOGENERATE_FILE_NOT_EXISTS and AUTOGENERATE_EVAL are supported.'); | ||
| } | ||
|
|
||
| return $proxyManagerConfiguration; |
There was a problem hiding this comment.
Creating ProxyManagerConfiguration on-demand as the class is not required when LazyGhostObjects are used.
| * | ||
| * @internal | ||
| */ | ||
| final class Autoloader |
There was a problem hiding this comment.
This class is copied from Doctrine\ORM\Proxy\Autoloader.
| return static function (InternalProxy $proxy, mixed $identifier) use ($persister, $classMetadata, $factory): void { | ||
| $original = $persister->load([$classMetadata->identifier => $identifier], $proxy); | ||
|
|
||
| if (! $original && ! $factory->lifecycleEventManager->documentNotFound($proxy, $identifier)) { | ||
| throw DocumentNotFoundException::documentNotFound($classMetadata->getName(), $identifier); | ||
| } | ||
|
|
||
| // phpcs:ignore SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed | ||
| if ($proxy instanceof NotifyPropertyChanged) { | ||
| $proxy->addPropertyChangedListener($factory->uow); | ||
| } | ||
| }; |
There was a problem hiding this comment.
Initialization code copied from StaticProxyFactory.
| * @template T of object | ||
| */ | ||
| public function getProxy(ClassMetadata $metadata, $identifier): GhostObjectInterface; | ||
| public function getProxy(ClassMetadata $metadata, $identifier): object; |
There was a problem hiding this comment.
The interface is modified, but child classes can be more restrictive. This is not a BC break for implementers of the interface, but it can be for users of the interface.
| public static function isLazyObject(object $document): bool | ||
| { | ||
| return $document instanceof InternalProxy || $document instanceof LazyLoadingInterface; | ||
| } |
There was a problem hiding this comment.
Most test changes are related to check interfaces to assert if the class is a lazy proxy object. I wonder if this method should be in UOW.
Later, it will use ReflectionClass::getLazyInitializer() to detect native lazy object.
|
|
||
| /** | ||
| * Generate proxy classes using Symfony VarExporter's LazyGhostTrait if true. | ||
| * Otherwise, use ProxyManager's LazyLoadingGhostFactory (deprecated) | ||
| */ | ||
| public function setUseLazyGhostObject(bool $flag): void | ||
| { | ||
| if ($flag === false) { | ||
| if (! class_exists(ProxyManagerConfiguration::class)) { | ||
| throw new LogicException('Package "friendsofphp/proxy-manager-lts" is required to disable LazyGhostObject.'); | ||
| } | ||
|
|
||
| trigger_deprecation( | ||
| 'doctrine/mongodb-odm', | ||
| '2.6', | ||
| 'Using "friendsofphp/proxy-manager-lts" is deprecated. Use "symfony/var-exporter" LazyGhostObjects instead.', | ||
| ); | ||
| } | ||
|
|
||
| $this->useLazyGhostObject = $flag; | ||
| } | ||
|
|
||
| public function isLazyGhostObjectEnabled(): bool | ||
| { | ||
| return $this->useLazyGhostObject ?? true; | ||
| } |
There was a problem hiding this comment.
Should we use the same method names as the ORM: isLazyGhostObjectEnabled and setLazyGhostObjectEnabled?
lib/Doctrine/ODM/MongoDB/Proxy/Factory/LazyGhostProxyFactory.php
Outdated
Show resolved
Hide resolved
|
Considering the unchecked checkboxes in your initial PR description, is this a WIP? |
631e341 to
cbab97c
Compare
|
I've just rebased this PR. The bundle will need an update to register the autoloader. Regarding native lazy objects and prop hooks PR on ODM, I think the approaches are not conflicting this this PR. |
alcaeus
left a comment
There was a problem hiding this comment.
Just some minor comments on this. I think the "BC Break" in the ProxyFactory interface is fine - proxies are an implementation detail and as long as we communicate that we change the default proxy mechanism we'll be fine. People shouldn't rely on a specific proxy behaviour, other than "it behaves as if it was an instance of the original class".
| } | ||
|
|
||
| /** @deprecated */ | ||
| public function getProxyManagerConfiguration(): ProxyManagerConfiguration |
There was a problem hiding this comment.
Note that this will return a new configuration instance every time this is called. I don't recall if there were any issues with that approach (e.g. due to unique identifiers in directories), so it's worth checking that creating a separate configuration doesn't cause the proxy manager to look for proxy files in different directories.
There was a problem hiding this comment.
I updated to keep the instance in memory so that it's still possible to customize the configuration of the proxy manager directly. But it is reset each time a configuration is set on the ODM configuration class.
lib/Doctrine/ODM/MongoDB/Proxy/Factory/LazyGhostProxyFactory.php
Outdated
Show resolved
Hide resolved
cbab97c to
0798779
Compare
0798779 to
4d4c864
Compare
|
I just found an incompatibility with DoctrineMongoDBODMBundle, the |
Summary
Use the
LazyGhostTraitfromsymfony/var-exporterto generate lazy proxy classes.LazyGhostProxyFactorythat implements theProxyFactoryinterface and use it by defaultlazy-ghost-objects