Skip to content

Deprecate values that are not shaped like a GUID in GuidType - #7504

Open
GromNaN wants to merge 1 commit into
doctrine:4.5.xfrom
GromNaN:guid-type-shape-deprecation
Open

Deprecate values that are not shaped like a GUID in GuidType#7504
GromNaN wants to merge 1 commit into
doctrine:4.5.xfrom
GromNaN:guid-type-shape-deprecation

Conversation

@GromNaN

@GromNaN GromNaN commented Aug 20, 2026

Copy link
Copy Markdown
Member

Fix symfony/symfony#17488

GuidType extends StringType and converts nothing, so any value reaches the database as is.

On a platform with a native GUID type, the driver is the one that rejects a malformed value. PostgreSQL answers SQLSTATE[22P02]: Invalid text representation: invalid input syntax for uuid: "asdf", which surfaces as a driver exception rather than as a conversion exception. On a platform without a native GUID type, the column is a plain CHAR(36) and holds anything, so the same value is silently stored and read back.

That inconsistency leaks into the ecosystem. In the Symfony Doctrine bridge, the uuid and ulid types refuse what they cannot convert (AbstractUidType), so a consumer can catch a ConversionException and report an invalid value. The guid type gives no such guarantee, which is why symfony/symfony#65497 proposed to re-implement a GUID shape check in ORMQueryBuilderLoader.

This patch deprecates handling a value that is not shaped like a GUID, in both conversion directions. The value is still returned unchanged in 4.5. The exception is announced for 5.0, in line with how making a type stricter was handled before (BC BREAK: Stricter DateTime types, BC BREAK: BIGINT values are cast to int if possible).

The accepted shape is 32 hexadecimal digits, with optional surrounding braces and an optional hyphen after any group of four digits. That is everything PostgreSQL accepts for its native uuid type, so no value the database could have stored is reported as malformed. Braces must be balanced.

The case to watch when 5.0 lands: an application storing something other than a GUID in a guid column on a platform without a native type. Such a column should use the string type instead.

GuidType extends StringType and converts nothing, so any value goes through. On a
platform with a native GUID type, the driver rejects a malformed value, for
instance PostgreSQL reporting an invalid input syntax for uuid. On a platform
without one, the column is a plain CHAR(36) and holds anything.

Deprecate handling a value that is not shaped like a GUID, in both conversion
directions, so the type can reject it in 5.0 the way the uuid and ulid types of
the Symfony Doctrine bridge already do.
@morozov

morozov commented Aug 30, 2026

Copy link
Copy Markdown
Member

Personally, I don't think that this is the right change:

  1. It allows UUID syntax that Postgres understands but other databases don't (e.g. SQL Server accepts neither 7c620edaea7911eb9a030242ac130003 nor {7c620edaea7911eb9a030242ac130003}). testValidValueIsPassedThrough() will likely fail if converted to an integration test (exactly the same problem as the one being solved).
  2. This is inconsistent with the other types. None of them validates the syntax of a value coming from the application — they accept a native PHP representation instead. The DateTime* types take a value object. The JSON type doesn't parse the JSON string. The integer type parses nothing either — it blindly casts to an int on the way back, although that's a bad behavior.

The current behavior where the target database rejects the write seems right to me, because the UUID format and constraints are database-specific. Uniform behavior across databases should be achieved by representing UUIDs as value objects and formatting them at binding time (similar to the DateTime* types).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants