Проблема с преобразованием доктрины UUID v4 в приложении Symfony

Сообщество переполнения стека,

Я столкнулся с проблемой обработки UUID версии 4 в моем приложении Symfony при использовании Doctrine для извлечения связанных объектов из базы данных. Несмотря на настройку моих сущностей на использование UUID в качестве идентификаторов и обеспечение их поддержки моей базой данных, я продолжаю сталкиваться с проблемами преобразования.

Описание проблемы:

После перехода от использования строковых идентификаторов к UUID (v4) для идентификаторов объектов я столкнулся с постоянной проблемой, когда Doctrine, похоже, неправильно обрабатывает преобразование UUID, особенно при извлечении связанных объектов. Ошибка проявляется в том, что Doctrine генерирует запрос с UUID в двоичном формате (например, 0x546970E77A10401388351FA21F92E31A), который не соответствует ни одной записи из-за несоответствия формата.

Наиболее заметное влияние наблюдается при попытке использовать метод getEmailsTo() к моей сущности EmailFormType для извлечения связанных EmailTo сущностей. Метод возвращает нулевые значения, что указывает на то, что записи не найдены, предположительно из-за проблемы с форматом UUID.

Соответствующие фрагменты кода:

  1. Объект EmailFormType (упрощенный):

    #[ORM\Entity(repositoryClass: EmailFormTypeRepository::class)]
    #[ORM\Table(name: 'WORKSPACE_EMAIL_FORM_TYPE')]
    class EmailFormType {
        #[ORM\Id]
        #[ORM\Column(name:"id", type: UuidType::NAME, unique: true, nullable: false)]
        #[ORM\GeneratedValue(strategy: 'CUSTOM')]
        #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
        private Uuid $id;
        // Other properties and methods...
        /**
          * @var Collection
        */
        #[ORM\OneToMany(mappedBy: 'emailFormType', targetEntity: EmailTo::class)]
        private Collection $emailsTo;
         /**
          *
          */
          public function __construct()
          {
             $this->emailsTo = new ArrayCollection();
          }
        public function getEmailsTo(): Collection
        {
         return $this->emailsTo;
        }
    }
    
  2. Функция получения писем:

    public function getFormattedEmails(EmailFormType $emailFormType, string $type): string {
        return implode(';', $emailFormType->getEmailsTo()
            ->filter(fn(EmailTo $emailTo) => $emailTo->getType() === $type)
            ->map(fn(EmailTo $emailTo) => $emailTo->getEmail())
            ->toArray());
    }
    

Мое поле в моей базе данных ORACLE:

ИД --- VARCHAR2(100)

Выполненный запрос:

SELECT t0.id AS ID_1, t0.email AS EMAIL_2, t0.type AS TYPE_3, t0.email_form_type_id AS EMAIL_FORM_TYPE_ID_4 FROM WORKSPACE_EMAIL_TO t0 WHERE t0.email_form_type_id = 0x546970E77A10401388351FA21F92E31A;

Любая помощь или рекомендации по этому вопросу будут очень признательны!

Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Symfony Station Communiqué - 17 февраля 2023 г
Symfony Station Communiqué - 17 февраля 2023 г
Это коммюнике первоначально появилось на Symfony Station , вашем источнике передовых новостей Symfony, PHP и кибербезопасности.
Управление ответами api для исключений на Symfony с помощью KernelEvents
Управление ответами api для исключений на Symfony с помощью KernelEvents
Много раз при создании api нам нужно возвращать клиентам разные ответы в зависимости от возникшего исключения.
1
0
661
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я столкнулся с проблемой при попытке сохранить тип VARCHAR2(100) для поля идентификатора моей сущности в базе данных ORACLE, и вот как я ее решил, обеспечив правильную обработку UUID:

  1. Создание настраиваемого типа. Я создал настраиваемый тип поля для обработки UUID.
  2. Обновление конфигурации: я добавил этот пользовательский тип в свою конфигурацию doctrine.yaml.
  3. Модификация сущности: я обновил свою сущность, чтобы использовать этот тип настраиваемого поля.

Вот класс, представляющий тип моего настраиваемого поля:

<?php

namespace App\Doctrine;

use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type;
use Symfony\Component\Uid\Uuid;

class CustomUuidType extends Type
{
    public function convertToDatabaseValue($value, AbstractPlatform $platform): mixed
    {
        return $value instanceof Uuid ? $value->toRfc4122() : $value;
    }

    // Ensure this method can return null for nullable fields
    public function convertToPHPValue($value, AbstractPlatform $platform): ?Uuid
    {
        return $value === null ? null : Uuid::fromString($value);
    }

    public function getName(): string
    {
        return 'custom_uuid';
    }

    public function getSQLDeclaration(array $column, AbstractPlatform $platform): string
    {
        return $platform->getColumnDeclarationSQL('varchar', $column);
    }
}

Модификация файла doctrine.yaml:

doctrine:
    dbal:
        types:
            custom_uuid: App\Doctrine\CustomUuidType

Моя настройка объекта:

#[ORM\Entity(repositoryClass: EmailFormTypeRepository::class)]
#[ORM\Table(name: 'WORKSPACE_EMAIL_FORM_TYPE')]
class EmailFormType
{
    #[ORM\Id]
    #[ORM\Column(name:"id", type:"custom_uuid", length: 100, unique: true, nullable: false)]
    #[ORM\GeneratedValue(strategy: 'CUSTOM')]
    #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
    private Uuid $id;

    #[ORM\OneToMany(mappedBy: 'emailFormType', targetEntity: EmailTo::class)]
    private Collection $emailsTo;

    public function __construct()
    {
        $this->emailsTo = new ArrayCollection();
    }

    public function getId(): Uuid
    {
        return $this->id;
    }

    public function getEmailsTo(): Collection
    {
        return $this->emailsTo;
    }
}

Благодаря этим изменениям Doctrine теперь правильно выполняет запросы с правильной обработкой преобразования UUID:

SELECT t0.id AS ID_1, t0.email AS EMAIL_2, t0.type AS TYPE_3, t0.email_form_type_id AS EMAIL_FORM_TYPE_ID_4 FROM WORKSPACE_EMAIL_TO t0 WHERE t0.email_form_type_id = ?
Parameters:
[
  "546970e7-7a10-4013-8835-1fa21f92e31a"
]

Эта настройка гарантирует, что мое приложение правильно обрабатывает UUID как VARCHAR2(100) в базе данных, одновременно используя мощные возможности Symfony Doctrine ORM.

Другие вопросы по теме