Skip to content

Commit 31b209c

Browse files
committed
add lazy hydrator
1 parent dc33c9d commit 31b209c

File tree

3 files changed

+94
-1
lines changed

3 files changed

+94
-1
lines changed

src/LazyHydrator.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Patchlevel\Hydrator;
6+
7+
use ReflectionClass;
8+
9+
final class LazyHydrator implements Hydrator
10+
{
11+
public function __construct(
12+
private readonly Hydrator $realHydrator,
13+
) {
14+
}
15+
16+
/**
17+
* @param class-string<T> $class
18+
* @param array<string, mixed> $data
19+
*
20+
* @return T
21+
*
22+
* @template T of object
23+
*/
24+
public function hydrate(string $class, array $data): object
25+
{
26+
return (new ReflectionClass($class))->newLazyProxy(
27+
function () use ($class, $data): object {
28+
return $this->realHydrator->hydrate($class, $data);
29+
},
30+
);
31+
}
32+
33+
/** @return array<string, mixed> */
34+
public function extract(object $object): array
35+
{
36+
return $this->realHydrator->extract($object);
37+
}
38+
}

tests/Benchmark/HydratorWithCryptographyBench.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Patchlevel\Hydrator\Cryptography\PersonalDataPayloadCryptographer;
99
use Patchlevel\Hydrator\Cryptography\Store\InMemoryCipherKeyStore;
1010
use Patchlevel\Hydrator\Hydrator;
11+
use Patchlevel\Hydrator\LazyHydrator;
1112
use Patchlevel\Hydrator\MetadataHydrator;
1213
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileCreated;
1314
use Patchlevel\Hydrator\Tests\Benchmark\Fixture\ProfileId;
@@ -31,7 +32,7 @@ public function __construct()
3132
PersonalDataPayloadCryptographer::createWithDefaultSettings($this->store),
3233
));
3334

34-
$this->hydrator = MetadataHydrator::create(eventDispatcher: $eventDispatcher);
35+
$this->hydrator = new LazyHydrator(MetadataHydrator::create(eventDispatcher: $eventDispatcher));
3536
}
3637

3738
public function setUp(): void

tests/Unit/LazyHydratorTest.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Unit;
6+
7+
use Patchlevel\Hydrator\Hydrator;
8+
use Patchlevel\Hydrator\LazyHydrator;
9+
use Patchlevel\Hydrator\Tests\Unit\Fixture\Email;
10+
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileCreated;
11+
use Patchlevel\Hydrator\Tests\Unit\Fixture\ProfileId;
12+
use PHPUnit\Framework\Attributes\RequiresPhp;
13+
use PHPUnit\Framework\TestCase;
14+
15+
#[RequiresPhp('>= 8.4')]
16+
class LazyHydratorTest extends TestCase
17+
{
18+
public function testNoHydration(): void
19+
{
20+
$realHydrator = $this->createMock(Hydrator::class);
21+
$realHydrator->expects($this->never())->method('hydrate')->withAnyParameters();
22+
23+
$hydrator = new LazyHydrator($realHydrator);
24+
25+
$object = $hydrator->hydrate(
26+
ProfileCreated::class,
27+
['profileId' => '1', 'email' => 'info@patchlevel.de'],
28+
);
29+
30+
self::assertInstanceOf(ProfileCreated::class, $object);
31+
}
32+
33+
public function testTriggerHydration(): void
34+
{
35+
$realHydrator = $this->createMock(Hydrator::class);
36+
$realHydrator->expects($this->once())->method('hydrate')->with(
37+
ProfileCreated::class,
38+
['profileId' => '1', 'email' => 'info@patchlevel.de'],
39+
)->willReturn(new ProfileCreated(
40+
profileId: ProfileId::fromString('1'),
41+
email: Email::fromString('info@patchlevel.de'),
42+
));
43+
44+
$hydrator = new LazyHydrator($realHydrator);
45+
46+
$object = $hydrator->hydrate(
47+
ProfileCreated::class,
48+
['profileId' => '1', 'email' => 'info@patchlevel.de'],
49+
);
50+
51+
self::assertInstanceOf(ProfileCreated::class, $object);
52+
self::assertSame('1', $object->profileId->toString());
53+
}
54+
}

0 commit comments

Comments
 (0)