Serialization

Basics

By default, PHP does not have any way to serialize and deserialize POPO objects. Aphiria provides this functionality without bleeding into your code. The best part is that you don't have to worry about how to (de)serialize nested objects or arrays of objects - Aphiria does it for you. Serializing an object is as easy as:

$user = new User(123, 'foo@bar.com');
$serializer = new JsonSerializer();
$serializer->serialize($user); // {"id":123,"email":"foo@bar.com"}

Similarly, deserializing an object is simple:

$serializedUser = '{"id":123,"email":"foo@bar.com"}';
$user = $serializer->deserialize($serializedUser, User::class);

Serializers

Aphiria provides the following serializers:

Under the hood, serializing works like this:

Value → encoded value → serialized value

Deserializing works in the reverse order:

Serialized value → decoded value → deserialized value

Form URL-Encoded Serializer

FormUrlEncodedSerializer can (de)serialize values to and from form URL-encoded strings. It's useful for things like (de)serializing values for use in a query string or in request/response bodies. Creating one is simple:

use Aphiria\Serialization\FormUrlEncodedSerializer;

$serializer = new FormUrlEncodedSerializer();

JSON Serializer

JsonSerializer is able to serialize and deserialize values to and from JSON. You can create an instance like this:

use Aphiria\Serialization\JsonSerializer;

$serializer = new JsonSerializer();

Arrays of Values

To deserialize an array of values, append the $type parameter with []:

$serializer->deserialize($serializedUsers, 'User[]');

This will cause each value in $serializedUsers to be deserialized as an instance of User.

You don't have to do anything special to serialize an array of values - just pass it in, and Aphiria will know what to do:

$serializer->serialize($users);

Note: Aphiria only supports arrays that contain a single type of value. In other words, you cannot mix and match different types in a single array.

Encoders

Encoders define how to map your POPOs to values that a serializer can (de)serialize. For most objects, this involves mapping an object to and from an associative array. An EncodingContext is passed during encoding/decoding to track things like circular references.

Default Encoders

To make it easier for you, Aphiria encodes/decodes array and DateTime values via the ArrayEncoder and DateTimeEncoder. DefaultEncoderRegistrant registers these default encoders for you. If you use this registrant, but want to customize some behavior, you can pass in a property name formatter and date format:

$encoders = new EncoderRegistry();
$encoderRegistrant = new DefaultEncoderRegistrant(
    new CamelCasePropertyNameFormatter(),
    'F j, Y'
);
$encoderRegistrant->registerDefaultEncoders($encoders);
// Pass $encoders into your serializer constructor...

Object Encoder

ObjectEncoder uses reflection to get all the properties in a class, and creates an associative array of property names to encoded property values. It even handles nested objects. When decoding, ObjectEncoder scans the constructor parameters and decodes them using the type hints on the parameters, and then sets any public properties. For best results, be sure to type your constructor parameters and class properties whenever possible.

Note: Since PHP has no typed arrays, it's impossible for ObjectEncoder to know how to decode an array of objects by type hints alone. If your constructor requires an array of objects, register a custom encoder.

Ignored Properties

Sometimes, you might want to ignore some properties when serializing your object. You can specify them like so:

// Create encoder registry...
$objectEncoder = new ObjectEncoder($encoders);
$objectEncoder->addIgnoredProperty(YourClass::class, 'nameOfPropertyToIgnore');
$encoders->registerDefaultObjectEncoder($objectEncoder);
// Pass $encoders into your serializer constructor...

You can also specify an array of property names in addIgnoredProperty().

Property Name Formatters

You might find yourself wanting to make your property names' formats consistent (eg camelCase). You can use an IPropertyNameFormatter to accomplish this. CamelCasePropertyNameFormatter and SnakeCasePropertyNameFormatter come out of the box. To use one (or your own), pass it into DefaultEncoderRegistrant.

Custom Encoders

Due to PHP's type limitations, there are some objects that Aphiria simply can't (de)serialize automatically. Some examples include:

In these cases, you can register your own encoder (which must implement IEncoder) to the encoder registry:

// Create encoder registry...
$encoders->registerEncoder(YourClass::class, new YourEncoder());
// Pass $encoders into your serializer constructor...

Now, whenever an instance of YourClass needs to be (de)serialized, YourEncoder will be used.

DateTime Encoder

DateTime objects are typically serialized to a formatted date string, and deserialized from that string back to an instance of DateTime. Aphiria provides DateTimeEncoder to provide this functionality. By default, it uses ISO 8601 when (de)serializing DateTime, DateTimeImmutable, and DateTimeInterface objects, but you can customize the format.