From e7ae6b63cf95d308e9b2cf617e810e466a60975c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Mon, 3 Nov 2025 09:49:33 +0100 Subject: [PATCH 1/3] Disable proxy class generation when using Native Lazy Objects --- .../DoctrineMongoDBExtension.php | 6 ++++++ src/DoctrineMongoDBBundle.php | 4 ++++ tests/DependencyInjection/ConfigurationTest.php | 6 ++---- tests/TestCase.php | 16 +++++++++++++--- 4 files changed, 25 insertions(+), 7 deletions(-) diff --git a/src/DependencyInjection/DoctrineMongoDBExtension.php b/src/DependencyInjection/DoctrineMongoDBExtension.php index 28e5a2d9..9c53cea5 100644 --- a/src/DependencyInjection/DoctrineMongoDBExtension.php +++ b/src/DependencyInjection/DoctrineMongoDBExtension.php @@ -472,6 +472,12 @@ public function load(array $configs, ContainerBuilder $container): void $configuratorDefinition->addMethodCall('loadTypes', [$config['types']]); } + // Disable proxy class generation for PHP 8.4 native lazy objects + if ($config['enable_native_lazy_objects']) { + $config['auto_generate_proxy_classes'] = ODMConfiguration::AUTOGENERATE_NEVER; + $container->removeDefinition('doctrine_mongodb.odm.proxy_cache_warmer'); + } + // set some options as parameters and unset them $config = $this->overrideParameters($config, $container); diff --git a/src/DoctrineMongoDBBundle.php b/src/DoctrineMongoDBBundle.php index 79a2a5f5..ef20d251 100644 --- a/src/DoctrineMongoDBBundle.php +++ b/src/DoctrineMongoDBBundle.php @@ -77,6 +77,10 @@ public function boot(): void private function registerAutoloader(DocumentManager $documentManager): void { $configuration = $documentManager->getConfiguration(); + if ($configuration->isNativeLazyObjectEnabled() || $configuration->isLazyGhostObjectEnabled()) { + return; + } + if ($configuration->getAutoGenerateProxyClasses() !== Configuration::AUTOGENERATE_FILE_NOT_EXISTS) { return; } diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index cab2d55b..3832e806 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -10,13 +10,13 @@ use Doctrine\Bundle\MongoDBBundle\Tests\Fixtures\Filter\DisabledFilter; use Doctrine\Bundle\MongoDBBundle\Tests\Fixtures\Repository\CustomGridFSRepository; use Doctrine\Bundle\MongoDBBundle\Tests\Fixtures\Repository\CustomRepository; +use Doctrine\Bundle\MongoDBBundle\Tests\TestCase; use Doctrine\ODM\MongoDB\Configuration as ODMConfiguration; use Doctrine\ODM\MongoDB\Repository\DefaultGridFSRepository; use Doctrine\ODM\MongoDB\Repository\DocumentRepository; use Generator; use PHPUnit\Framework\Attributes\DataProvider; use PHPUnit\Framework\Attributes\Group; -use PHPUnit\Framework\TestCase; use Symfony\Bridge\PhpUnit\ExpectDeprecationTrait; use Symfony\Component\Config\Definition\Exception\InvalidConfigurationException; use Symfony\Component\Config\Definition\Processor; @@ -28,8 +28,6 @@ use function file_get_contents; use function method_exists; -use const PHP_VERSION_ID; - class ConfigurationTest extends TestCase { use ExpectDeprecationTrait; @@ -45,7 +43,7 @@ public function testDefaults(): void 'auto_generate_proxy_classes' => ODMConfiguration::AUTOGENERATE_EVAL, 'auto_generate_persistent_collection_classes' => ODMConfiguration::AUTOGENERATE_NEVER, 'enable_lazy_ghost_objects' => method_exists(ODMConfiguration::class, 'setUseLazyGhostObject'), - 'enable_native_lazy_objects' => PHP_VERSION_ID >= 80400 && method_exists(ODMConfiguration::class, 'setUseNativeLazyObject'), + 'enable_native_lazy_objects' => self::useNativeLazyObject(), 'default_database' => 'default', 'document_managers' => [], 'connections' => [], diff --git a/tests/TestCase.php b/tests/TestCase.php index 65b504fe..403f7b37 100644 --- a/tests/TestCase.php +++ b/tests/TestCase.php @@ -32,14 +32,24 @@ public static function createTestDocumentManager(array $paths = []): DocumentMan $config->setMetadataDriverImpl(new AttributeDriver($paths)); $config->setMetadataCache(new ArrayAdapter()); - if (PHP_VERSION_ID >= 80400 && method_exists($config, 'setUseLazyGhostObject')) { + if (self::useNativeLazyObject()) { + $config->setUseNativeLazyObject(true); + } elseif (self::useLazyGhostObject()) { $config->setUseLazyGhostObject(true); - } elseif (method_exists($config, 'setUseLazyGhostObject')) { - $config->setUseLazyGhostObject(false); } $uri = getenv('MONGODB_URI') ?: throw new RuntimeException('The MONGODB_URI environment variable is not set.'); return DocumentManager::create(new Client($uri), $config); } + + public static function useNativeLazyObject(): bool + { + return PHP_VERSION_ID >= 80400 && method_exists(Configuration::class, 'setUseNativeLazyObject'); + } + + public static function useLazyGhostObject(): bool + { + return method_exists(Configuration::class, 'setUseLazyGhostObject') && ! self::useNativeLazyObject(); + } } From 0c97fbd8b42148ca7d6a882eb66a4fc8aa43a308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Wed, 5 Nov 2025 07:07:10 -0500 Subject: [PATCH 2/3] WIP tests --- .../AbstractMongoDBExtensionTestCase.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/DependencyInjection/AbstractMongoDBExtensionTestCase.php b/tests/DependencyInjection/AbstractMongoDBExtensionTestCase.php index 6222e5bf..9554c992 100644 --- a/tests/DependencyInjection/AbstractMongoDBExtensionTestCase.php +++ b/tests/DependencyInjection/AbstractMongoDBExtensionTestCase.php @@ -45,7 +45,10 @@ public function testDependencyInjectionConfigurationDefaults(): void $loader->load(DoctrineMongoDBExtensionTest::buildConfiguration(), $container); $this->assertEquals('MongoDBODMProxies', $container->getParameter('doctrine_mongodb.odm.proxy_namespace')); - $this->assertEquals(Configuration::AUTOGENERATE_EVAL, $container->getParameter('doctrine_mongodb.odm.auto_generate_proxy_classes')); + $this->assertEquals( + self::useNativeLazyObject() ? Configuration::AUTOGENERATE_NEVER : Configuration::AUTOGENERATE_EVAL, + $container->getParameter('doctrine_mongodb.odm.auto_generate_proxy_classes'), + ); $config = DoctrineMongoDBExtensionTest::buildConfiguration([ 'proxy_namespace' => 'MyProxies', @@ -375,7 +378,7 @@ public function testDependencyInjectionImportsOverrideDefaults(): void $container->getCompilerPassConfig()->setRemovingPasses([]); $container->compile(); - $this->assertTrue((bool) $container->getParameter('doctrine_mongodb.odm.auto_generate_proxy_classes')); + $this->assertSame(self::useNativeLazyObject(), ! $container->getParameter('doctrine_mongodb.odm.auto_generate_proxy_classes')); } public function testResolveTargetDocument(): void From 428be5249b72447d0984fcf04c761b7f049ebf57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Tamarelle?= Date: Fri, 14 Nov 2025 18:13:54 +0100 Subject: [PATCH 3/3] PHPStan --- phpstan-baseline.neon | 20 +++++++------------ .../DependencyInjection/ConfigurationTest.php | 3 +-- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 125cb07e..02a3168c 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -528,18 +528,6 @@ parameters: count: 1 path: tests/DependencyInjection/AbstractMongoDBExtensionTestCase.php - - - message: '#^Call to function method_exists\(\) with ''Doctrine\\\\ODM\\\\MongoDB\\\\Configuration'' and ''setUseLazyGhostObje…'' will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: tests/DependencyInjection/ConfigurationTest.php - - - - message: '#^Call to function method_exists\(\) with ''Doctrine\\\\ODM\\\\MongoDB\\\\Configuration'' and ''setUseNativeLazyObj…'' will always evaluate to true\.$#' - identifier: function.alreadyNarrowedType - count: 1 - path: tests/DependencyInjection/ConfigurationTest.php - - message: '#^Method Doctrine\\Bundle\\MongoDBBundle\\Tests\\DependencyInjection\\ConfigurationTest\:\:testFullConfiguration\(\) has parameter \$config with no value type specified in iterable type array\.$#' identifier: missingType.iterableValue @@ -829,7 +817,13 @@ parameters: path: tests/ServiceRepositoryTest.php - - message: '#^Call to function method_exists\(\) with Doctrine\\ODM\\MongoDB\\Configuration and ''setUseLazyGhostObje…'' will always evaluate to true\.$#' + message: '#^Call to function method_exists\(\) with ''Doctrine\\\\ODM\\\\MongoDB\\\\Configuration'' and ''setUseLazyGhostObje…'' will always evaluate to true\.$#' + identifier: function.alreadyNarrowedType + count: 1 + path: tests/TestCase.php + + - + message: '#^Call to function method_exists\(\) with ''Doctrine\\\\ODM\\\\MongoDB\\\\Configuration'' and ''setUseNativeLazyObj…'' will always evaluate to true\.$#' identifier: function.alreadyNarrowedType count: 1 path: tests/TestCase.php diff --git a/tests/DependencyInjection/ConfigurationTest.php b/tests/DependencyInjection/ConfigurationTest.php index 3832e806..e7b3e800 100644 --- a/tests/DependencyInjection/ConfigurationTest.php +++ b/tests/DependencyInjection/ConfigurationTest.php @@ -26,7 +26,6 @@ use function array_key_exists; use function array_merge; use function file_get_contents; -use function method_exists; class ConfigurationTest extends TestCase { @@ -42,7 +41,7 @@ public function testDefaults(): void 'auto_generate_hydrator_classes' => false, 'auto_generate_proxy_classes' => ODMConfiguration::AUTOGENERATE_EVAL, 'auto_generate_persistent_collection_classes' => ODMConfiguration::AUTOGENERATE_NEVER, - 'enable_lazy_ghost_objects' => method_exists(ODMConfiguration::class, 'setUseLazyGhostObject'), + 'enable_lazy_ghost_objects' => self::useLazyGhostObject(), 'enable_native_lazy_objects' => self::useNativeLazyObject(), 'default_database' => 'default', 'document_managers' => [],