Skip to content

Commit 7513d65

Browse files
committed
[ObjectMapper] lazy map relations
1 parent 9b32764 commit 7513d65

File tree

6 files changed

+75
-3
lines changed

6 files changed

+75
-3
lines changed

src/Symfony/Component/ObjectMapper/ObjectMapper.php

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@ public function map(object $source, object|string|null $target = null): object
161161
}
162162
}
163163

164-
if (!$mappingToObject && !$map?->transform && $targetConstructor) {
164+
if (!$map?->transform && $targetConstructor) {
165165
try {
166166
$mappedTarget->__construct(...$ctorArguments);
167167
} catch (\ReflectionException $e) {
@@ -182,7 +182,7 @@ public function map(object $source, object|string|null $target = null): object
182182
}
183183

184184
if ($objectMapInitialized) {
185-
$this->objectMap = null;
185+
// $this->objectMap = null;
186186
}
187187

188188
return $mappedTarget;
@@ -237,7 +237,16 @@ private function getSourceValue(object $source, object $target, mixed $value, \S
237237
} elseif ($objectMap->offsetExists($value)) {
238238
$value = $objectMap[$value];
239239
} else {
240-
$value = ($this->objectMapper ?? $this)->map($value, $mapTo->target);
240+
if (\PHP_VERSION_ID >= 80400) {
241+
$refl = new \ReflectionClass($mapTo->target);
242+
$mapper = $this->objectMapper ?? $this;
243+
244+
return $refl->newLazyProxy(static function () use ($mapper, $value, $objectMap, $mapTo) {
245+
return $objectMap[$value] = $mapper->map($value, $mapTo->target);
246+
});
247+
}
248+
249+
return ($this->objectMapper ?? $this)->map($value, $mapTo->target);
241250
}
242251
}
243252

@@ -371,3 +380,4 @@ public function withObjectMapper(ObjectMapperInterface $objectMapper): static
371380
return $clone;
372381
}
373382
}
383+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy;
4+
5+
use Symfony\Component\ObjectMapper\Attribute\Map;
6+
7+
#[Map(target: OrderTarget::class)]
8+
class OrderSource
9+
{
10+
public ?int $id = null;
11+
public ?UserSource $user = null;
12+
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy;
4+
5+
class OrderTarget
6+
{
7+
public ?int $id = null;
8+
public ?UserTarget $user = null;
9+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy;
4+
5+
use Symfony\Component\ObjectMapper\Attribute\Map;
6+
7+
#[Map(target: UserTarget::class)]
8+
class UserSource
9+
{
10+
public ?string $name = null;
11+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?php
2+
3+
namespace Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy;
4+
5+
class UserTarget
6+
{
7+
public ?string $name = null;
8+
}

src/Symfony/Component/ObjectMapper/Tests/ObjectMapperTest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,10 @@
3232
use Symfony\Component\ObjectMapper\Tests\Fixtures\DeeperRecursion\RecursiveDto;
3333
use Symfony\Component\ObjectMapper\Tests\Fixtures\DeeperRecursion\Relation;
3434
use Symfony\Component\ObjectMapper\Tests\Fixtures\DeeperRecursion\RelationDto;
35+
use Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy\OrderSource;
36+
use Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy\OrderTarget;
37+
use Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy\UserSource;
38+
use Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultLazy\UserTarget;
3539
use Symfony\Component\ObjectMapper\Tests\Fixtures\DefaultValueStdClass\TargetDto;
3640
use Symfony\Component\ObjectMapper\Tests\Fixtures\Flatten\TargetUser;
3741
use Symfony\Component\ObjectMapper\Tests\Fixtures\Flatten\User;
@@ -559,4 +563,22 @@ public function testTransformCollection()
559563

560564
$this->assertEquals([new TransformCollectionD('a'), new TransformCollectionD('b')], $transformed->foo);
561565
}
566+
567+
#[RequiresPhp('>=8.4')]
568+
public function testEmbedsAreLazyLoadedByDefault()
569+
{
570+
$mapper = new ObjectMapper();
571+
$source = new OrderSource();
572+
$source->id = 123;
573+
$source->user = new UserSource();
574+
$source->user->name = 'Test User';
575+
$target = $mapper->map($source, OrderTarget::class);
576+
$this->assertInstanceOf(OrderTarget::class, $target);
577+
$this->assertSame(123, $target->id);
578+
$this->assertInstanceOf(UserTarget::class, $target->user);
579+
$refl = new \ReflectionClass(UserTarget::class);
580+
$this->assertTrue($refl->isUninitializedLazyObject($target->user));
581+
$this->assertSame('Test User', $target->user->name);
582+
$this->assertFalse($refl->isUninitializedLazyObject($target->user));
583+
}
562584
}

0 commit comments

Comments
 (0)