diff --git a/CacheWarmer/DoctrineMetadataCacheWarmer.php b/CacheWarmer/DoctrineMetadataCacheWarmer.php new file mode 100644 index 000000000..d6ae59d42 --- /dev/null +++ b/CacheWarmer/DoctrineMetadataCacheWarmer.php @@ -0,0 +1,37 @@ +entityManager = $entityManager; + + parent::__construct($phpArrayFile); + } + + /** + * @param string $cacheDir + * + * @return bool false if there is nothing to warm-up + */ + protected function doWarmUp($cacheDir, ArrayAdapter $arrayAdapter) + { + $metadataFactory = new ClassMetadataFactory(); + $metadataFactory->setEntityManager($this->entityManager); + $metadataFactory->setCacheDriver(new DoctrineProvider($arrayAdapter)); + $metadataFactory->getAllMetadata(); + + return true; + } +} diff --git a/DependencyInjection/DoctrineExtension.php b/DependencyInjection/DoctrineExtension.php index 07afe8f6a..8e9e77871 100644 --- a/DependencyInjection/DoctrineExtension.php +++ b/DependencyInjection/DoctrineExtension.php @@ -2,6 +2,7 @@ namespace Doctrine\Bundle\DoctrineBundle\DependencyInjection; +use Doctrine\Bundle\DoctrineBundle\CacheWarmer\DoctrineMetadataCacheWarmer; use Doctrine\Bundle\DoctrineBundle\Dbal\ManagerRegistryAwareConnectionProvider; use Doctrine\Bundle\DoctrineBundle\Dbal\RegexSchemaAssetFilter; use Doctrine\Bundle\DoctrineBundle\DependencyInjection\Compiler\ServiceRepositoryCompilerPass; @@ -21,6 +22,8 @@ use Symfony\Bridge\Doctrine\SchemaListener\PdoCacheAdapterDoctrineSchemaSubscriber; use Symfony\Bridge\Doctrine\Validator\DoctrineLoader; use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\DoctrineAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\Cache\DoctrineProvider; use Symfony\Component\Config\FileLocator; use Symfony\Component\DependencyInjection\Alias; @@ -814,6 +817,11 @@ protected function loadOrmCacheDrivers(array $entityManager, ContainerBuilder $c $this->loadCacheDriver('metadata_cache', $entityManager['name'], $entityManager['metadata_cache_driver'], $container); $this->loadCacheDriver('result_cache', $entityManager['name'], $entityManager['result_cache_driver'], $container); $this->loadCacheDriver('query_cache', $entityManager['name'], $entityManager['query_cache_driver'], $container); + + if (! $container->getParameter('kernel.debug')) { + $this->registerMetadataPhpArrayCacheWarmer($entityManager['name'], $container); + $this->registerMetadataPhpArrayCache($entityManager['name'], $container); + } } /** @@ -927,4 +935,36 @@ private function createArrayAdapterCachePool(ContainerBuilder $container, string return $id; } + + private function registerMetadataPhpArrayCacheWarmer(string $entityManagerName, ContainerBuilder $container): void + { + $cacheWarmerDefinition = $container->register(sprintf('doctrine.orm.%s_metadata_cache.php_array_warmer', $entityManagerName), DoctrineMetadataCacheWarmer::class); + $cacheWarmerDefinition->setArguments([ + new Reference(sprintf('doctrine.orm.%s_entity_manager', $entityManagerName)), + $this->getPhpArrayFile($entityManagerName), + ]); + $cacheWarmerDefinition->addTag('kernel.cache_warmer'); + } + + private function registerMetadataPhpArrayCache(string $entityManagerName, ContainerBuilder $container): void + { + $aliasId = sprintf('doctrine.orm.%s_metadata_cache', $entityManagerName); + $serviceId = (string) $container->getAlias($aliasId); + + $phpArrayAdapterDefinition = new Definition(PhpArrayAdapter::class, [ + $this->getPhpArrayFile($entityManagerName), + new Definition(DoctrineAdapter::class, [new Reference($serviceId)]), + ]); + + $serviceId .= '.php_array'; + + $doctrineCacheDefinition = $container->register($serviceId, DoctrineProvider::class); + $doctrineCacheDefinition->addArgument($phpArrayAdapterDefinition); + $container->setAlias($aliasId, $serviceId); + } + + private function getPhpArrayFile(string $entityManagerName): string + { + return '%kernel.cache_dir%' . sprintf('/doctrine/orm/%s_metadata.php', $entityManagerName); + } } diff --git a/Tests/DependencyInjection/DoctrineExtensionTest.php b/Tests/DependencyInjection/DoctrineExtensionTest.php index a0e568e8f..633540941 100644 --- a/Tests/DependencyInjection/DoctrineExtensionTest.php +++ b/Tests/DependencyInjection/DoctrineExtensionTest.php @@ -12,6 +12,8 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Doctrine\Messenger\DoctrineClearEntityManagerWorkerSubscriber; use Symfony\Component\Cache\Adapter\ArrayAdapter; +use Symfony\Component\Cache\Adapter\DoctrineAdapter; +use Symfony\Component\Cache\Adapter\PhpArrayAdapter; use Symfony\Component\Cache\DoctrineProvider; use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass; use Symfony\Component\DependencyInjection\ContainerBuilder; @@ -347,6 +349,18 @@ public function testDependencyInjectionConfigurationDefaults(): void $definition = $container->getDefinition((string) $container->getAlias('doctrine.orm.default_metadata_cache')); $this->assertEquals(DoctrineProvider::class, $definition->getClass()); $arguments = $definition->getArguments(); + $this->assertInstanceOf(Definition::class, $arguments[0]); + $this->assertEquals(PhpArrayAdapter::class, $arguments[0]->getClass()); + $arguments = $arguments[0]->getArguments(); + $this->assertSame('%kernel.cache_dir%/doctrine/orm/default_metadata.php', $arguments[0]); + $this->assertInstanceOf(Definition::class, $arguments[1]); + $this->assertEquals(DoctrineAdapter::class, $arguments[1]->getClass()); + $arguments = $arguments[1]->getArguments(); + $this->assertInstanceOf(Reference::class, $arguments[0]); + $this->assertEquals('doctrine.orm.cache.provider.cache.doctrine.orm.default.metadata', (string) $arguments[0]); + $definition = $container->getDefinition((string) $arguments[0]); + $this->assertEquals(DoctrineProvider::class, $definition->getClass()); + $arguments = $definition->getArguments(); $this->assertInstanceOf(Reference::class, $arguments[0]); $this->assertEquals('cache.doctrine.orm.default.metadata', (string) $arguments[0]); $this->assertSame(ArrayAdapter::class, $container->getDefinition((string) $arguments[0])->getClass()); @@ -803,7 +817,7 @@ public static function cacheConfigurationProvider(): array return [ 'metadata_cache_default' => [ 'expectedAliasName' => 'doctrine.orm.default_metadata_cache', - 'expectedAliasTarget' => 'doctrine.orm.cache.provider.cache.doctrine.orm.default.metadata', + 'expectedAliasTarget' => 'doctrine.orm.cache.provider.cache.doctrine.orm.default.metadata.php_array', 'cacheName' => 'metadata_cache_driver', 'cacheConfig' => ['type' => null], ], @@ -822,7 +836,7 @@ public static function cacheConfigurationProvider(): array 'metadata_cache_pool' => [ 'expectedAliasName' => 'doctrine.orm.default_metadata_cache', - 'expectedAliasTarget' => 'doctrine.orm.cache.provider.metadata_cache_pool', + 'expectedAliasTarget' => 'doctrine.orm.cache.provider.metadata_cache_pool.php_array', 'cacheName' => 'metadata_cache_driver', 'cacheConfig' => ['type' => 'pool', 'pool' => 'metadata_cache_pool'], ], @@ -841,7 +855,7 @@ public static function cacheConfigurationProvider(): array 'metadata_cache_service' => [ 'expectedAliasName' => 'doctrine.orm.default_metadata_cache', - 'expectedAliasTarget' => 'service_target_metadata', + 'expectedAliasTarget' => 'service_target_metadata.php_array', 'cacheName' => 'metadata_cache_driver', 'cacheConfig' => ['type' => 'service', 'id' => 'service_target_metadata'], ],