You are browsing a version that has not yet been released. |
Converting Custom DBAL Types
When hydrating, the hydrator converts the values of mapped fields into the
PHP type of the field, based on the Doctrine mapping. This page describes
the built-in conversions, and how to add conversions for custom DBAL types. For instance, a
timestamp or a string is converted to a DateTime instance for a field
of type datetime, and a string is converted to an enum for a field
mapped with enumType.
The conversion is applied after the strategy of a field, if there is one. Values that already have the expected PHP type are kept as they are. The type converter is inherited by the hydrators of associated entities, see Configuring Associated Entities.
The fields of embeddables are converted by their own types when
embeddables are represented as arrays, see
Embeddables as Arrays. The type converter
receives them by their full name, e.g. address.postalCode.
Default Conversions
| Doctrine type | Hydrated value |
|---|---|
integer, smallint |
int |
float, smallfloat |
float |
boolean |
bool |
string, ascii_string, text, guid, enum, bigint, decimal |
string |
number |
BCMath\Number (PHP 8.4 with bcmath) |
date, time, datetime, datetime_utc, datetimetz |
DateTime from a timestamp, a string or a DateTimeImmutable |
date_immutable, time_immutable, datetime_immutable, datetime_utc_immutable, datetimetz_immutable |
DateTimeImmutable from a timestamp, a string or a DateTime |
dateinterval |
DateInterval from an ISO 8601 duration, optionally with a leading + or - |
The built-in conversions keep null, and convert an empty string to
null for date, time and date interval fields. Values of other types, like json,
simple_array, binary, blob or custom types, are not converted.
Enums
Doctrine ORM supports backed enums
through the enumType option of a column. The hydrator uses this option
to convert backing values into enums, no further configuration is needed:
enum Suit: string { case Hearts = 'H'; case Diamonds = 'D'; case Clubs = 'C'; case Spades = 'S';}#[Entity]class Card{ /** ... */ #[Column(type: 'string', enumType: Suit::class)] private Suit $suit; public function getSuit(): Suit { return $this->suit; } public function setSuit(Suit $suit): void { $this->suit = $suit; }}$hydrator = new DoctrineHydrator($entityManager);$card = $hydrator->hydrate(['suit' => 'H'], new Card());echo $card->getSuit()->name; // prints "Hearts"
Backing values from forms are strings, they are converted to integers for
enums backed by integers. An invalid backing value causes a ValueError.
For fields without enumType, add the BackedEnumStrategy of
laminas-hydrator to the field:
use Laminas\Hydrator\Strategy\BackedEnumStrategy;$hydrator->addStrategy('suit', new BackedEnumStrategy(Suit::class));
Converting Values when Extracting
By default, extract() returns enums, date and time values and date
intervals as they are. To extract them as scalar values instead, for instance to serialize an entity to JSON,
pass a configured type converter to the hydrator:
use Doctrine\Laminas\Hydrator\DoctrineObject as DoctrineHydrator;use Doctrine\Laminas\Hydrator\DoctrineTypeConverter;$hydrator = new DoctrineHydrator( $entityManager, typeConverter: new DoctrineTypeConverter(extractEnums: true, extractDateTimes: true),);$data = $hydrator->extract($card);echo $data['suit']; // prints "H"
With extractEnums, enums are extracted as their backing value. With
extractDateTimes, date and time values are extracted as strings: fields
of type date as Y-m-d, fields of type time as H:i:s, all
other fields in the DateTimeInterface::ATOM format, and date intervals
in the format of Doctrine DBAL, e.g. +P01Y02M03DT04H05M06S. The
extracted values can be hydrated again.
As when hydrating, the conversion is applied after the strategy of a field, and only to values of the type that is converted.
Custom Conversions
Values of custom Doctrine types, like a custom DBAL type uuid, are not
converted by default. To convert them, implement
Doctrine\Laminas\Hydrator\TypeConverterInterface for the type:
use Doctrine\Laminas\Hydrator\TypeConverterInterface;use Doctrine\Persistence\Mapping\ClassMetadata;final class UuidTypeConverter implements TypeConverterInterface{ public function hydrate(mixed $value, ClassMetadata $metadata, string $fieldName): mixed { return is_string($value) && $value !== '' ? Uuid::fromString($value) : $value; } public function extract(mixed $value, ClassMetadata $metadata, string $fieldName): mixed { return $value; }}
Then register it by the name of the Doctrine type:
use Doctrine\Laminas\Hydrator\DoctrineObject as DoctrineHydrator;use Doctrine\Laminas\Hydrator\DoctrineTypeConverter;$hydrator = new DoctrineHydrator( $entityManager, typeConverter: new DoctrineTypeConverter(typeConverters: [ 'uuid' => new UuidTypeConverter(), ]),);
A registered converter is used for all fields of its type, in both
directions, and receives all values including null. It replaces the
built-in conversion of the type, so you can also register converters for
types like datetime to change how they are converted. Fields mapped
with enumType are always converted to enums.
If your custom DBAL type is able to convert the values your application
receives, you can use it in the converter, e.g.
Type::getType('uuid')->convertToPHPValue($value, $platform). Note that
DBAL types convert values in the format of the database, which may differ
from the format of form data.
For conversions that do not depend on the type of a field only, implement the interface for all fields and decorate the default converter:
use Doctrine\Laminas\Hydrator\DoctrineTypeConverter;use Doctrine\Laminas\Hydrator\TypeConverterInterface;use Doctrine\Persistence\Mapping\ClassMetadata;final class AppTypeConverter implements TypeConverterInterface{ public function __construct( private TypeConverterInterface $inner = new DoctrineTypeConverter(), ) { } public function hydrate(mixed $value, ClassMetadata $metadata, string $fieldName): mixed { if ($fieldName === 'slug' && is_string($value)) { return strtolower($value); } return $this->inner->hydrate($value, $metadata, $fieldName); } public function extract(mixed $value, ClassMetadata $metadata, string $fieldName): mixed { return $this->inner->extract($value, $metadata, $fieldName); }}$hydrator = new DoctrineHydrator($entityManager, typeConverter: new AppTypeConverter());
To change the conversion of a single field of a single entity only, add a strategy to that field instead.
