diff --git a/src/Configuration.php b/src/Configuration.php index 5825926e390..252e86f9b09 100644 --- a/src/Configuration.php +++ b/src/Configuration.php @@ -9,6 +9,8 @@ use Doctrine\ORM\Cache\CacheConfiguration; use Doctrine\ORM\Exception\InvalidEntityRepository; use Doctrine\ORM\Internal\Hydration\AbstractHydrator; +use Doctrine\ORM\Internal\Hydration\DefaultHydratorFactory; +use Doctrine\ORM\Internal\Hydration\HydratorFactory; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataFactory; use Doctrine\ORM\Mapping\DefaultEntityListenerResolver; @@ -47,6 +49,16 @@ class Configuration extends \Doctrine\DBAL\Configuration /** @phpstan-var array, ClassMetadata::GENERATOR_TYPE_*> */ private $identityGenerationPreferences = []; + public function setHydratorFactory(HydratorFactory $factory): void + { + $this->attributes['hydratorFactory'] = $factory; + } + + public function getHydratorFactory(): HydratorFactory + { + return $this->attributes['hydratorFactory'] ?? new DefaultHydratorFactory(); + } + /** @phpstan-param array, ClassMetadata::GENERATOR_TYPE_*> $value */ public function setIdentityGenerationPreferences(array $value): void { diff --git a/src/EntityManager.php b/src/EntityManager.php index 2e160393417..462b812fc48 100644 --- a/src/EntityManager.php +++ b/src/EntityManager.php @@ -10,12 +10,12 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\LockMode; use Doctrine\ORM\Exception\EntityManagerClosed; -use Doctrine\ORM\Exception\InvalidHydrationMode; use Doctrine\ORM\Exception\MissingIdentifierField; use Doctrine\ORM\Exception\MissingMappingDriverImplementation; use Doctrine\ORM\Exception\ORMException; use Doctrine\ORM\Exception\UnrecognizedIdentifierFields; use Doctrine\ORM\Internal\Hydration\AbstractHydrator; +use Doctrine\ORM\Internal\Hydration\HydratorFactory; use Doctrine\ORM\Mapping\ClassMetadata; use Doctrine\ORM\Mapping\ClassMetadataFactory; use Doctrine\ORM\Proxy\DefaultProxyClassNameResolver; @@ -104,6 +104,11 @@ class EntityManager implements EntityManagerInterface */ private Cache|null $cache = null; + /** + * The hydrator factory to use. + */ + private HydratorFactory $hydratorFactory; + /** * Creates a new EntityManager that operates on the given database connection * and uses the given Configuration and EventManager implementations. @@ -150,6 +155,8 @@ public function __construct( $cacheFactory = $cacheConfig->getCacheFactory(); $this->cache = $cacheFactory->createCache($this); } + + $this->hydratorFactory = $this->config->getHydratorFactory(); } public function getConnection(): Connection @@ -545,15 +552,7 @@ public function getUnitOfWork(): UnitOfWork public function newHydrator(string|int $hydrationMode): AbstractHydrator { - return match ($hydrationMode) { - Query::HYDRATE_OBJECT => new Internal\Hydration\ObjectHydrator($this), - Query::HYDRATE_ARRAY => new Internal\Hydration\ArrayHydrator($this), - Query::HYDRATE_SCALAR => new Internal\Hydration\ScalarHydrator($this), - Query::HYDRATE_SINGLE_SCALAR => new Internal\Hydration\SingleScalarHydrator($this), - Query::HYDRATE_SIMPLEOBJECT => new Internal\Hydration\SimpleObjectHydrator($this), - Query::HYDRATE_SCALAR_COLUMN => new Internal\Hydration\ScalarColumnHydrator($this), - default => $this->createCustomHydrator((string) $hydrationMode), - }; + return $this->hydratorFactory->create($this, $this->config, $hydrationMode); } public function getProxyFactory(): ProxyFactory @@ -621,15 +620,4 @@ private function configureMetadataCache(): void $this->metadataFactory->setCache($metadataCache); } - - private function createCustomHydrator(string $hydrationMode): AbstractHydrator - { - $class = $this->config->getCustomHydrationMode($hydrationMode); - - if ($class !== null) { - return new $class($this); - } - - throw InvalidHydrationMode::fromMode($hydrationMode); - } } diff --git a/src/Internal/Hydration/DefaultHydratorFactory.php b/src/Internal/Hydration/DefaultHydratorFactory.php new file mode 100644 index 00000000000..1d9ad0bae4d --- /dev/null +++ b/src/Internal/Hydration/DefaultHydratorFactory.php @@ -0,0 +1,37 @@ + new ObjectHydrator($em), + Query::HYDRATE_ARRAY => new ArrayHydrator($em), + Query::HYDRATE_SCALAR => new ScalarHydrator($em), + Query::HYDRATE_SINGLE_SCALAR => new SingleScalarHydrator($em), + Query::HYDRATE_SIMPLEOBJECT => new SimpleObjectHydrator($em), + Query::HYDRATE_SCALAR_COLUMN => new ScalarColumnHydrator($em), + default => $this->createCustomHydrator((string) $hydrationMode, $em, $config), + }; + } + + private function createCustomHydrator(string $hydrationMode, EntityManagerInterface $em, Configuration $config): AbstractHydrator + { + $class = $config->getCustomHydrationMode($hydrationMode); + + if ($class !== null) { + return new $class($em); + } + + throw InvalidHydrationMode::fromMode($hydrationMode); + } +} diff --git a/src/Internal/Hydration/HydratorFactory.php b/src/Internal/Hydration/HydratorFactory.php new file mode 100644 index 00000000000..1338141c21a --- /dev/null +++ b/src/Internal/Hydration/HydratorFactory.php @@ -0,0 +1,19 @@ +