Symfony: UUID, Doctrine a Elastic Search Bundle
25. 12. 2022Upozornění: v příspěvku se nebudeme zabývat smyslem použití UUID ani výhody či nevýhody. Ukážeme si jak snadno UUID integrovat do projektu Symfony s Doctrine a ES bundlem od autorů FOS.
Předpokladem pro pokračování je že máte již u sebe zprovozněné Symfony s integrací Doctrine a vše je plně funkční. Jako první krok provedeme za pomoci Composer instalaci UID komponenty pro získání generátoru UUID.
$ composer require symfony/uid
V dalším kroku vytvoříme entitu kde jako její unikátní identifikátor použijeme UUID záznam. Jelikož Doctrina již v sobě obsahuje podporu UID tak nastavení je velice snadné.
<?php declare(strict_types=1);
namespace Acme\Entity;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\CustomIdGenerator;
use Doctrine\ORM\Mapping\Entity;
use Doctrine\ORM\Mapping\GeneratedValue;
use Doctrine\ORM\Mapping\Id;
use Symfony\Component\Uid\Uuid;
#[Entity]
class Example
{
#[Id]
#[Column(type: 'uuid', unique: true)]
#[GeneratedValue(strategy: 'CUSTOM')]
#[CustomIdGenerator(class: 'doctrine.uuid_generator')]
private ?Uuid $id = null;
...
}
V nadcházejícím kroku provedeme instalaci a konfiguraci FOSElasticBundlu dle dokumentace https://github.com/FriendsOfSymfony/FOSElasticaBundle/blob/master/doc/setup.md
$ composer require friendsofsymfony/elastica-bundle
Při použití auto increment by již stačilo na závěr přidat pouze konfiguraci automatického mapování, ale protože se UUID ukládá do sloupce jako BINARY a knihovna nepodporuje UID konverze, tak musíme přidat vlastní třídu “elastica_to_model_transformer”. Budeme vycházet z původního řešení https://github.com/FriendsOfSymfony/FOSElasticaBundle/blob/master/src/Doctrine/ORM/ElasticaToModelTransformer.php které zkopírujeme a přidáme převod IDs na správný formát pr výběr dat z databáze za pomoci Doctrine.
<?php declare(strict_types=1);
namespace Acme\Elastic;
use Doctrine\ORM\QueryBuilder;
use FOS\ElasticaBundle\Doctrine\AbstractElasticaToModelTransformer;
use Symfony\Component\Uid\Uuid;
class ElasticaToModelTransformer extends AbstractElasticaToModelTransformer
{
…
/**
* @param array $identifierValues
* @param $hydrate
* @return array|float|int|mixed|string
*/
protected function findByIdentifiers(array $identifierValues, $hydrate): mixed
{
if (empty($identifierValues)) {
return [];
}
$identifierValues = array_map(fn($y) => Uuid::fromString($y)->toBinary(), $identifierValues);
$qb = $this->getEntityQueryBuilder();
$qb
->andWhere(
$qb
->expr()
->in(static::ENTITY_ALIAS . '.' . $this->options['identifier'], ':values')
)
->setParameter('values', $identifierValues);
$query = $qb->getQuery();
foreach ($this->options['hints'] as $hint) {
$query->setHint($hint['name'], $hint['value']);
}
return $query->execute();
}
…
}
A nakonec přidáme vlastní třídu transformace do konfigurace.
fos_elastica:
indexes:
acme:
persistence:
elastica_to_model_transformer:
service: Acme\Elastic\ElasticaToModelTransformer