UuidGenerator attribute is ignored by Doctrine #7123

Open
opened 2026-01-22 15:45:09 +01:00 by admin · 4 comments
Owner

Originally created by @kgrozdanovski on GitHub (Mar 29, 2023).

Bug Report

Q A
BC Break no
Version 2.14.1

Summary

UuidGenerator attribute is ignored

Current behavior

When persisting an entity with a UUID type for the id property, as per Symfony's and Doctrine's documentation, Doctrine
fails to identify the built-in UuidGenerator and defaults to attempting to create a sequential ID (since the database column is defined as uuid in Postgres the query ultimately fails since it cannot find <table>_id_seq.

How to reproduce

Doctrine ORM version 2.14.1
PHP version 8.2
Postgresql for Docker, image tag postgres:15

The above versions are provided for context however considering the following analysis they seem to be irrelevant.

My entity property definition:

    #[ORM\Id]
    #[ORM\Column(type: UuidType::NAME, unique: true)]
    #[ORM\GeneratedValue(strategy: 'UUID')]
    #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')]
    private Uuid|string|null $id = null;

Additionally I have attempted to use strategy: 'CUSTOM' though that yielded the same result.

I have traced this problem to a missing 'instance' property, which is only ever defined by the MappingDriver::loadMetadataForClass() method, however this method is never called since the AttributeDriver class is used instead, and in that class only the 'class' property is set but no the 'instance' property:

// Mapping\Driver\AttributeDriver.php :: loadMetadataForClass()
$metadata->setCustomGeneratorDefinition(
    [
        'class' => $customGeneratorAttribute->class,
    ]
);

Compared to the MappingDriver from doctrine-bundle:

// Mapping\MappingDriver.php :: loadMetadataForClass()
$idGenerator = $this->idGeneratorLocator->get($metadata->customGeneratorDefinition['class']);
$metadata->setCustomGeneratorDefinition(['instance' => $idGenerator] + $metadata->customGeneratorDefinition);
$metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE);

This instance property is referenced in the ClassMetadataFactory class from doctrine-bundle:

// Mapping\ClassMetadataFactory.php :: doLoadMetadata()
if (! isset($customGeneratorDefinition['instance'])) {
    return;
}

assert($customGeneratorDefinition['instance'] instanceof AbstractIdGenerator);

Since this method returns void, the custom ID generator (UuidGenerator in this case) is never set.

Expected behavior

The ORM should invoke the gen_random_uuid() database function to generate a UUID value.

Originally created by @kgrozdanovski on GitHub (Mar 29, 2023). ### Bug Report | Q | A |------------ | ------ | BC Break | no | Version | 2.14.1 #### Summary UuidGenerator attribute is ignored #### Current behavior When persisting an entity with a UUID type for the `id` property, as per Symfony's and Doctrine's documentation, Doctrine fails to identify the built-in UuidGenerator and defaults to attempting to create a sequential ID (since the database column is defined as `uuid` in Postgres the query ultimately fails since it cannot find `<table>_id_seq`. #### How to reproduce Doctrine ORM version `2.14.1` PHP version `8.2` Postgresql for Docker, image tag `postgres:15` *The above versions are provided for context however considering the following analysis they seem to be irrelevant.* My entity property definition: ```php #[ORM\Id] #[ORM\Column(type: UuidType::NAME, unique: true)] #[ORM\GeneratedValue(strategy: 'UUID')] #[ORM\CustomIdGenerator(class: 'doctrine.uuid_generator')] private Uuid|string|null $id = null; ``` Additionally I have attempted to use `strategy: 'CUSTOM'` though that yielded the same result. I have traced this problem to a missing 'instance' property, which is only ever defined by the `MappingDriver::loadMetadataForClass()` method, however this method is never called since the `AttributeDriver` class is used instead, and in that class only the 'class' property is set but no the 'instance' property: ```php // Mapping\Driver\AttributeDriver.php :: loadMetadataForClass() $metadata->setCustomGeneratorDefinition( [ 'class' => $customGeneratorAttribute->class, ] ); ``` Compared to the MappingDriver from doctrine-bundle: ```php // Mapping\MappingDriver.php :: loadMetadataForClass() $idGenerator = $this->idGeneratorLocator->get($metadata->customGeneratorDefinition['class']); $metadata->setCustomGeneratorDefinition(['instance' => $idGenerator] + $metadata->customGeneratorDefinition); $metadata->setIdGeneratorType(ClassMetadataInfo::GENERATOR_TYPE_NONE); ``` This `instance` property is referenced in the `ClassMetadataFactory` class from doctrine-bundle: ```php // Mapping\ClassMetadataFactory.php :: doLoadMetadata() if (! isset($customGeneratorDefinition['instance'])) { return; } assert($customGeneratorDefinition['instance'] instanceof AbstractIdGenerator); ``` Since this method returns void, the custom ID generator (`UuidGenerator` in this case) is never set. #### Expected behavior The ORM should invoke the `gen_random_uuid()` database function to generate a UUID value.
Author
Owner

@greg0ire commented on GitHub (Mar 29, 2023):

There might be a bug in the attribute driver, but please note that the UuidGenerator is deprecated since https://github.com/doctrine/orm/pull/8813

See also: https://github.com/doctrine/dbal/pull/3212

@greg0ire commented on GitHub (Mar 29, 2023): There might be a bug in the attribute driver, but please note that the `UuidGenerator` is deprecated since https://github.com/doctrine/orm/pull/8813 See also: https://github.com/doctrine/dbal/pull/3212
Author
Owner

@kgrozdanovski commented on GitHub (Mar 29, 2023):

There might be a bug in the attribute driver, but please note that the UuidGenerator is deprecated since #8813

See also: doctrine/dbal#3212

Thanks for the prompt reply.

Despite Doctrine's UuidGenerator being deprecated this would still seem to be a problem for all custom generators defined via PHP attributes.

@kgrozdanovski commented on GitHub (Mar 29, 2023): > There might be a bug in the attribute driver, but please note that the `UuidGenerator` is deprecated since #8813 > > See also: [doctrine/dbal#3212](https://github.com/doctrine/dbal/pull/3212) Thanks for the prompt reply. Despite Doctrine's `UuidGenerator` being deprecated this would still seem to be a problem for all custom generators defined via PHP attributes.
Author
Owner

@kgrozdanovski commented on GitHub (Apr 1, 2023):

After further debugging I traced the problem to another property being declared with the #[ORM\GeneratedValue] attribute (contained in another trait for common properties - e.g. date_created).
Apparently if you have multiple GeneratedValue attributes on different properties within an Entity class, they override the set type and in my case the type of the Generated value was overwritten - Doctrine determined it should use a Sequential generator instead of the desired UUID generator.
After removing the attribute from all properties except the ID this worked as expected.

In conclusion, I'm not sure if this is the intended behavior or not, but if it is, then I would recommend Doctrine throws a warning or exception when using multiple GeneratedValue attributes with different types within the same class. If it isn't and if the intended behavior is to support multiple generated values with different generators (which makes more sense) then there is still a bug however it should be rephrased to "Different GeneratedValue types not supported/working)".

I will leave the issue open until someone from the team decides what to do with this.

@kgrozdanovski commented on GitHub (Apr 1, 2023): After further debugging I traced the problem to another property being declared with the `#[ORM\GeneratedValue]` attribute (contained in another trait for common properties - e.g. `date_created`). Apparently if you have multiple `GeneratedValue` attributes on different properties within an Entity class, they override the set `type` and in my case the type of the Generated value was overwritten - Doctrine determined it should use a Sequential generator instead of the desired UUID generator. After removing the attribute from all properties except the ID this worked as expected. In conclusion, I'm not sure if this is the intended behavior or not, but if it is, then I would recommend Doctrine throws a warning or exception when using multiple `GeneratedValue` attributes with different types within the same class. If it isn't and if the intended behavior is to support multiple generated values with different generators (which makes more sense) then there is still a bug however it should be rephrased to "Different GeneratedValue types not supported/working)". I will leave the issue open until someone from the team decides what to do with this.
Author
Owner

@derrabus commented on GitHub (Apr 2, 2023):

The ORM's UUID generator is not compatible with Symfony's UUID type. And I don't really think that we should make them compatible, tbh. Just generate new UUIDs in your application. That's what UUIDs are made for.

@derrabus commented on GitHub (Apr 2, 2023): The ORM's UUID generator is not compatible with Symfony's UUID type. And I don't really think that we should make them compatible, tbh. Just generate new UUIDs in your application. That's what UUIDs are made for.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7123