PHP OOP __serialize() 和 __unserialize()

在面向对象编程(OOP)中,序列化(serialize)是将对象的状态转换为可存储或传输的格式的过程。反序列化(unserialize)则是将序列化后的数据重新构建成原始对象的过程。在PHP中,这两个过程分别由__serialize()__unserialize()魔术方法处理。

1. __serialize() 方法

当调用serialize()函数时,如果被序列化的对象定义了一个魔术方法__serialize(),那么这个方法会先被调用。该方法应该返回一个包含对象状态的字符串,以便在反序列化时重新构建对象。

例如:

class MyClass {
    public $var1;
    protected $var2;

    public function __construct($var1, $var2) {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }

    public function __serialize(): array {
        return [
            'var1' => $this->var1,
            // 不需要序列化受保护的成员,因为它们在反序列化时无法恢复
        ];
    }
}

在上面的例子中,__serialize()方法返回一个包含公共变量var1值的数组。受保护的变量var2未被序列化,因为它们在反序列化时无法恢复。

2. __unserialize() 方法

当调用unserialize()函数时,如果被反序列化的对象定义了一个魔术方法__unserialize(),那么这个方法会先被调用。该方法接受一个包含对象状态的数组作为参数,并使用它来重新构建对象。

例如:

class MyClass {
    public $var1;
    protected $var2;

    public function __construct($var1, $var2) {
        $this->var1 = $var1;
        $this->var2 = $var2;
    }

    public function __unserialize(array $data): void {
        $this->var1 = $data['var1'];
        // 受保护的成员无法恢复,需要在反序列化后手动初始化
        $this->var2 = null;
    }
}

在上面的例子中,__unserialize()方法使用传入的数组来设置公共变量var1的值。受保护的变量var2无法恢复,需要在反序列化后手动初始化。

3. 注意事项

  • __serialize()__unserialize()方法只能被定义为私有成员(private)。
  • 如果一个类没有定义__sleep()魔术方法,那么在序列化时,所有非静态的公共、受保护和私有属性都会被序列化。如果类中存在不可序列化的成员(例如资源或闭包),则序列化操作将失败。
  • 反序列化时,如果传入的数据格式错误或内容与对象的状态不匹配,则会产生警告或导致异常。因此,在实际应用中,需要对输入数据进行有效性检查。