From f352848e06773e00aedb70a245fff9acab712411 Mon Sep 17 00:00:00 2001 From: Joel Wurtz Date: Wed, 25 Feb 2026 13:19:02 +0100 Subject: [PATCH] feat(mapper): register mapper as lazy, reduce init call if sub mappers not used --- .../InjectMapperMethodStatementsGenerator.php | 5 +- src/LazyMapper.php | 87 +++++++++++++++++++ 2 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 src/LazyMapper.php diff --git a/src/Generator/InjectMapperMethodStatementsGenerator.php b/src/Generator/InjectMapperMethodStatementsGenerator.php index dfe7d17e..2b4cd3fe 100644 --- a/src/Generator/InjectMapperMethodStatementsGenerator.php +++ b/src/Generator/InjectMapperMethodStatementsGenerator.php @@ -4,10 +4,12 @@ namespace AutoMapper\Generator; +use AutoMapper\LazyMapper; use AutoMapper\Metadata\Dependency; use AutoMapper\Metadata\GeneratorMetadata; use PhpParser\Node\Arg; use PhpParser\Node\Expr; +use PhpParser\Node\Name; use PhpParser\Node\Scalar; use PhpParser\Node\Stmt; @@ -53,7 +55,8 @@ public function getStatements(Expr\Variable $automapperRegistryVariable, Generat new Expr\PropertyFetch(new Expr\Variable('this'), 'mappers'), new Scalar\String_($dependency->mapperDependency->name) ), - new Expr\MethodCall($automapperRegistryVariable, 'getMapper', [ + new Expr\New_(new Name(LazyMapper::class), [ + new Arg($automapperRegistryVariable), new Arg(new Scalar\String_($dependency->mapperDependency->source)), new Arg(new Scalar\String_($dependency->mapperDependency->target)), ]) diff --git a/src/LazyMapper.php b/src/LazyMapper.php new file mode 100644 index 00000000..86a2c278 --- /dev/null +++ b/src/LazyMapper.php @@ -0,0 +1,87 @@ + + * @template Target of object|array + * + * @phpstan-import-type MapperContextArray from MapperContext + * + * @internal + * + * @implements MapperInterface + */ +class LazyMapper implements MapperInterface +{ + /** @var MapperInterface|null */ + private ?MapperInterface $mapper = null; + + public function __construct( + private readonly AutoMapperRegistryInterface $registry, + /** @var 'array'|class-string */ + private readonly string $source, + /** @var 'array'|class-string */ + private readonly string $target, + ) { + } + + public function getTargetIdentifiers(mixed $value): mixed + { + $mapper = $this->getMapper(); + + if ($mapper instanceof GeneratedMapper) { + return $mapper->getTargetIdentifiers($value); + } + + return null; + } + + public function getSourceHash(mixed $value): string + { + $mapper = $this->getMapper(); + + if ($mapper instanceof GeneratedMapper) { + return $mapper->getSourceHash($value); + } + + return ''; + } + + public function getTargetHash(mixed $value): string + { + $mapper = $this->getMapper(); + + if ($mapper instanceof GeneratedMapper) { + return $mapper->getTargetHash($value); + } + + return ''; + } + + public function &map(mixed $value, array $context = []): mixed + { + return $this->getMapper()->map($value, $context); + } + + /** + * @return MapperInterface + */ + public function getMapper(): MapperInterface + { + if ($this->mapper === null) { + /** @var MapperInterface $mapper */ + $mapper = $this->registry->getMapper($this->source, $this->target); + + if ($mapper instanceof GeneratedMapper) { + $mapper->registerMappers($this->registry); + } + + $this->mapper = $mapper; + } + + return $this->mapper; + } +}