Skip to content

Commit 4b5bc9e

Browse files
committed
Documented ObjectRegistry related
1 parent dd1b56a commit 4b5bc9e

File tree

3 files changed

+93
-0
lines changed

3 files changed

+93
-0
lines changed

src/batch-doctrine-persistence/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ composer require yokai/batch-doctrine-persistence
2525
This package provides:
2626

2727
- an [item writer](docs/object-item-writer.md) that persists objects through object manager
28+
- an [object registry](docs/object-registry.md) that remembers found objects identities
2829

2930

3031
## Contribution
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Object registry
2+
3+
Imagine that in an `ItemJob` you need to find objects from a database.
4+
5+
```php
6+
use App\Entity\Product;
7+
use Doctrine\Persistence\ObjectRepository;
8+
use Yokai\Batch\Job\Item\ItemProcessorInterface;
9+
10+
class DenormalizeProductProcessor implements ItemProcessorInterface
11+
{
12+
public function __construct(
13+
private ObjectRepository $repository,
14+
) {
15+
}
16+
17+
/**
18+
* @param array<string, mixed> $item
19+
*/
20+
public function process(mixed $item): Product
21+
{
22+
$product = $this->repository->findOneBy(['sku' => $item['sku']]);
23+
24+
$product ??= new Product($item['sku']);
25+
26+
$product->setName($item['name']);
27+
$product->setPrice($item['price']);
28+
//...
29+
30+
return $product;
31+
}
32+
}
33+
```
34+
35+
The problem here is that every time you will call `findOneBy`, you will have to query the database.
36+
The object might already be in Doctrine's memory, so it won't be hydrated twice, but the query will be done every time.
37+
38+
The role of the `ObjectRegistry` is to remember found objects identities, and query these objects with it instead.
39+
40+
```diff
41+
use App\Entity\Product;
42+
-use Doctrine\Persistence\ObjectRepository;
43+
+use Yokai\Batch\Bridge\Doctrine\Persistence\ObjectRegistry;
44+
use Yokai\Batch\Job\Item\ItemProcessorInterface;
45+
46+
class DenormalizeProductProcessor implements ItemProcessorInterface
47+
{
48+
public function __construct(
49+
- private ObjectRepository $repository,
50+
+ private ObjectRegistry $registry,
51+
) {
52+
}
53+
54+
/**
55+
* @param array<string, mixed> $item
56+
*/
57+
public function process(mixed $item): Product
58+
{
59+
- $product = $this->repository->findOneBy(['sku' => $item['sku']]);
60+
+ $product = $this->registry->findOneBy(Product::class, ['sku' => $item['sku']]);
61+
62+
$product ??= new Product($item['sku']);
63+
64+
$product->setName($item['name']);
65+
$product->setPrice($item['price']);
66+
//...
67+
68+
return $product;
69+
}
70+
}
71+
```
72+
73+
The first time, the query will hit the database, and the object identity will be remembered in the registry.
74+
Everytime after that, the registry will call `Doctrine\Persistence\ObjectManager::find` instead.
75+
If the object is still in Doctrine's memory, it will be returned directly.
76+
Otherwise, the query will be the fastest possible because it will use the object identity.
77+
78+
79+
## On the same subject
80+
81+
- [What is an item job ?](https://github.com/yokai-php/batch/blob/0.x/docs/domain/item-job.md)

src/batch-doctrine-persistence/src/ObjectRegistry.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@
99
use Doctrine\Persistence\ObjectManager;
1010
use Yokai\Batch\Exception\InvalidArgumentException;
1111

12+
/**
13+
* This class will remember objects identifies when found.
14+
* Using it as a proxy to your queries will simplify queries afterward.
15+
*/
1216
final class ObjectRegistry
1317
{
1418
/**
@@ -22,6 +26,8 @@ public function __construct(
2226
}
2327

2428
/**
29+
* Finds a single object by a set of criteria.
30+
*
2531
* @template T of object
2632
*
2733
* @param class-string<T> $class
@@ -39,6 +45,8 @@ public function findOneBy(string $class, array $criteria): ?object
3945
}
4046

4147
/**
48+
* Finds a single object by using a callback to find it.
49+
*
4250
* @template T of object
4351
*
4452
* @param class-string<T> $class
@@ -72,6 +80,9 @@ public function findOneUsing(string $class, \Closure $closure, string $key = nul
7280
return $object;
7381
}
7482

83+
/**
84+
* Removes all remembered identities of all classes.
85+
*/
7586
public function reset(): void
7687
{
7788
$this->identities = [];

0 commit comments

Comments
 (0)