atto / hydrator
description
Requires
- php: ~8.2.0 || ~8.3.0
- atto/codegen-tools: ^0.1.0
- doctrine/instantiator: ^2.0
- roave/better-reflection: ^6.25
- symfony/console: ^6.4 || ^7.0
Requires (Dev)
- phpstan/phpstan: ^1.12.6
- phpunit/phpunit: ^10.2.0
This package is auto-updated.
Last update: 2025-01-31 12:32:20 UTC
README
The hydrator is designed to quickly serialise (extract) and deserialise (hydrate) complex objects.
It works out of the box on simple data structures. For anything else, behaviour can be defined to meet your needs.
Default Behaviour
Your DTO's properties are extracted into an array.
The value of each property is converted into a JSON string.
Arrays must specify a subtype. Arrays ordered integer keys (lists) are extracted into a nested JSON array. Arrays with specified keys are extracted into a nested JSON object.
Object are extracted into a nested JSON object.
If the default behaviour does not suit your needs; you can manually define alternate behaviour
Manually Defined Behaviour
Behaviour can be defined using attributes from the Atto\Hydrator\Attribute
namespace.
Serialization Strategy
Serialization strategies are only useful for arrays of data. They will have no impact on scalars. They cannot be used on objects.
The default strategy is to serialize as JSON.
// This is the default behaviour if omitted. #[SerializationStrategy(SerializationStrategyType::JSON)] private array $myList;
It may also be serialized to a comma-delimited or pipe-delimited list.
#[SerializationStrategy(SerializationStrategyType::CommaDelimited)] private array $myCommaDelimitedList; #[SerializationStrategy(SerializationStrategyType::PipeDelimited)] private array $myPipeDelimitedList;
CommaDelimited and PipeDelimited serialisation will:
- Only work for lists of simple data.
- Will lose your array keys.
Hydration Strategy
Json
Json will json encode your property before the entire object is json encoded.
class MyObject { #[HydrationStrategy(HydrationStrategyType::Json)] private MyNestedObject $myNestedObject; } class MyNestedObject { private int $myInt = 1; }
The hydrator will extract the following output:
['myNestedObject' => '{"myInt":1}']
Merge
Merge can only be used for a single level.
If you specify Merge on an object contains a nested object property. The nested object's properties are merged into the original object, as if it were its own properties.
class MyObject { #[HydrationStrategy(HydrationStrategyType::Merge)] private MyNestedObject $myNestedObject; } class MyNestedObject { private int $myInt = 1; }
The hydrator will extract the following output:
['myNestedObject_myInt' => 1]
If your property names include underscores, undefined behaviour MAY occur. Stick to camelCase property names for predictable behaviour.
Nest
Nest is the default behaviour of any property except DateTimes, Enums and Scalars.
You should never need to specify it explicitly.
class MyObject { #[HydrationStrategy(HydrationStrategyType::Nest)] private MyNestedObject $myNestedObject; } class MyNestedObject { private int $myInt = 1; }
The hydrator will extract the following output:
[ 'myNestedObject' => ['myInt' => 1], ]
Passthrough
Passthrough will leave your property pass through untouched.
If Passthrough is used, it should be used at every level above it as well.
StringWrapper
A StringWrapper is an object which; takes a single string argument to __construct
and returns it with __toString()
.
i.e.
class MyStringWrapper { public function __construct( private string $myString = 'Hello, World!', ) { } public function __toString() { return $this->myString; } }
For objects like this, we can serialise them as their constructor argument, a simple string.
"Hello, World!"
DateTime, Enum & Scalar
Datetimes, Enums and Scalars have their own default strategies.
They do not need to be specified, but they can be overriden if you choose.
Subtype
For an array, a subtype must be specified.
#[Subtype(\DateTime::class)] private array $listOfDateTimes
Arrays must only contain items of that subtype.
This is because, serialised data does not contain information of its type.
The hydrator uses this Subtype
attribute to determine what to hydrate each item as.