Symfony: UUID, Doctrine a Elastic Search Bundle

25. 12. 2022

Upozorně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

Nejnovější příspěvky