此处的文档有些误导性。在它说“此方法充当对象的析构函数。此方法之后不会调用__destruct()方法”的地方,我相信其意图并非对象的析构函数本身不会运行,而是析构函数不会/作为序列化过程的一部分/被调用。
也就是说,对象在超出范围时仍然会像正常一样被析构,但析构函数不会作为对象序列化的一部分被调用。
(PHP 5 >= 5.1.0, PHP 7, PHP 8)
Serializable::serialize — 对象的字符串表示
此函数没有参数。
返回对象的字符串表示或null
此处的文档有些误导性。在它说“此方法充当对象的析构函数。此方法之后不会调用__destruct()方法”的地方,我相信其意图并非对象的析构函数本身不会运行,而是析构函数不会/作为序列化过程的一部分/被调用。
也就是说,对象在超出范围时仍然会像正常一样被析构,但析构函数不会作为对象序列化的一部分被调用。
我不喜欢这里的糟糕文档,它们错误地声称“serialize(): 此方法充当对象的析构函数。此方法之后不会调用__destruct()方法”。
它们只是意味着serialize()不会调用__destruct()。这就是它们唯一的意思。
正在序列化的对象将继续作为普通对象存在。因此,您不应该将serialize()视为您的析构函数!将您的对象视为用户可能正在使用的仍然存活的副本!
析构函数将始终像平常一样在稍后运行,当您的对象超出范围(或被您强制unset())时。
带有证明的示例
<?php
class A implements Serializable
{
public $data = [];
public function __destruct()
{
echo "调用 A 的析构函数。\n";
}
public function serialize()
{
printf("- 调用 %s 的序列化。\n", static::class);
return serialize($this->data);
}
public function unserialize($serialized)
{
printf("- 调用 %s 的反序列化。\n", static::class);
$this->data = unserialize($serialized);
}
}
class B extends A
{
public function __destruct()
{
echo "调用 B 的析构函数。\n";
}
}
$a = new A();
$a->data['inner_b'] = new B();
var_dump($a);
echo "-----------------\n";
echo "调用 serialize($a):\n";
$str = serialize($a);
echo "-----------------\n";
echo "从这里开始脚本关闭:...\n";
?>
结果
```
object(A)#1 (1) {
["data"]=>
array(1) {
["inner_b"]=>
object(B)#2 (1) {
["data"]=>
array(0) {
}
}
}
}
-----------------
调用 serialize($a)
- 调用 A 的序列化。
- 调用 B 的序列化。
-----------------
从这里开始脚本关闭:...
调用 A 的析构函数。
调用 B 的析构函数。
```