PHP 7.4 : New custom object serialization mechanism
03, November 2021

If we want to customize php object serialization, currently we have only two option:

  • __sleep()/__wakeup() magic method
  • Serializable interface

But, both of them has some limitations and downsides. Serializable does not work reliably when used in nested serialize() calls. This situation can happen when we attempt to compose serialization through the use of parent::serialize().

Another issue is, to ensure unserialize() happens in correct context, it needs to be performed immediately. But this can lead to unsafe usage of object in unserialize(), as the object may not be fully initiated yet.

Also, as serialize() can return data in arbitrary format, making analyzing that data much harder than needed.


__sleep/__wakeup also have downside if serialized object needs to be significantly different than the object stat in memory.


To solve these issues, PHP 7.4 has introduced two new magic method to customize serialization.

// Returns array containing all the necessary state of the object.
public function __serialize(): array;

// Restores the object state from the given data array.
public function __unserialize(array $data): void;


With these new methods, we do not need to concern ourselves with serialize()/unserialize() calls anymore.

In __serialize() we simply need to return an array of datas that we need to serialize.

On the other side, __unserialize() just takes an array and we can populate our object with that data.


Here is a simple example:

<?php

class Student
{
    public string $name;
    public int $class;
    public int $roll;
    private float $gpa;
    
    public function __construct(string $name, int $class, int $roll, float $gpa)
    {
        $this->name = $name;
        $this->class = $class;
        $this->roll = $roll;
        $this->gpa = $gpa;
    }
    
    public function __serialize(): array
    {
        return [
            'name' => $this->name,
            'class' => $this->class,
            'roll' => $this->roll,
            'gpa' => $this->gpa,
        ];
    }
    
    public function __unserialize(array $data): void
    {
        $this->name = $data['name'];
        $this->class = $data['class'];
        $this->roll = $data['roll'];
        $this->gpa = $data['gpa'];
    }
}

$serialized = serialize(new Student('Bob', 10, 3, 4.00));

echo $serialized;
// O:7:"Student":4:{s:4:"name";s:3:"Bob";s:5:"class";i:10;s:4:"roll";i:3;s:3:"gpa";d:4;}

$unserialized = unserialize($serialized);

print_r($unserialized);
// Student Object (
//    [name] => Bob
//    [class] => 10
//    [roll] => 3
//    [gpa:Student:private] => 4
//)


RFC: https://wiki.php.net/rfc/custom_object_serialization


Write comment about this article: