Bridge with doctrine/persistence
Refer to the official documentation on Doctrine’s website.
This bridge provides SQL database querying mechanisms, whenever you need to read/write from it.
Along with utility classes for memory management in jobs execution.
Object item writer
The writer will persist every items on the appropriate
ObjectManager.It expect that items are objects.
Objects can belong to different
ObjectManager instances, only the encountered ones will be flushed.ObjectManager->flush() is called every time the ItemJob reaches the batch size.
<?php
declare(strict_types=1);
use Doctrine\Persistence\ManagerRegistry;
use Yokai\Batch\Bridge\Doctrine\Persistence\ObjectWriter;
/** @var ManagerRegistry $managerRegistry */
new ObjectWriter(
doctrine: $managerRegistry,
);
See also
Object registry util
Imagine that in an ItemJob you need to find objects from a database.
<?php
declare(strict_types=1);
use App\Entity\Product;
use Doctrine\Persistence\ObjectRepository;
use Yokai\Batch\Job\Item\ItemProcessorInterface;
final class DenormalizeProductProcessor implements ItemProcessorInterface
{
public function __construct(
private ObjectRepository $repository,
) {
}
/**
* @param array<string, mixed> $item
*/
public function process(mixed $item): Product
{
$product = $this->repository->findOneBy(['sku' => $item['sku']]);
$product ??= new Product($item['sku']);
$product->setName($item['name']);
$product->setPrice($item['price']);
//...
return $product;
}
}
The problem here is that every time you will call
findOneBy, you
will have to query the database. The object might already be inDoctrine’s memory, so it won’t be hydrated twice, but the query will be
done every time.
The role of the
ObjectRegistry is to remember found objects
identities, and query these objects with it instead.<?php
declare(strict_types=1);
use App\Entity\Product;
-use Doctrine\Persistence\ObjectRepository;
+use Yokai\Batch\Bridge\Doctrine\Persistence\ObjectRegistry;
use Yokai\Batch\Job\Item\ItemProcessorInterface;
final class DenormalizeProductProcessor implements ItemProcessorInterface
{
public function __construct(
- private ObjectRepository $repository,
+ private ObjectRegistry $registry,
) {
}
/**
* @param array<string, mixed> $item
*/
public function process(mixed $item): Product
{
- $product = $this->repository->findOneBy(['sku' => $item['sku']]);
+ $product = $this->registry->findOneBy(Product::class, ['sku' => $item['sku']]);
$product ??= new Product($item['sku']);
$product->setName($item['name']);
$product->setPrice($item['price']);
//...
return $product;
}
}
The first time, the query will hit the database, and the object identity
will be remembered in the registry.
Everytime after that, the registry will call
Doctrine\Persistence\ObjectManager::find instead.If the object is still in Doctrine’s memory, it will be returned directly.
Otherwise, the query will be the fastest possible because it will use the object identity.
See also