请注意,对象的静态成员不会被序列化。
serialize() 返回一个字符串,其中包含可以存储在 PHP 中的任何值的字节流表示。 unserialize() 可以使用此字符串来重新创建原始变量值。 使用 serialize 保存对象将保存对象中的所有变量。 对象中的方法不会被保存,只会保存类的名称。
为了能够 unserialize() 对象,该对象的类需要被定义。 也就是说,如果您有一个类 A 的对象并序列化它,您将获得一个引用类 A 并包含其中包含的所有变量值的字符串。 如果你想在另一个文件中反序列化它,一个类 A 的对象,类 A 的定义必须首先出现在那个文件中。 这可以通过将类 A 的类定义存储在一个包含文件中并包含该文件来完成,或者使用 spl_autoload_register() 函数。
<?php
// A.php:
class A {
public $one = 1;
public function show_one() {
echo $this->one;
}
}
// page1.php:
include "A.php";
$a = new A;
$s = serialize($a);
// 将 $s 存储在 page2.php 可以找到的位置。
file_put_contents('store', $s);
// page2.php:
// 这是为了让反序列化正常工作而必需的。
include "A.php";
$s = file_get_contents('store');
$a = unserialize($s);
// 现在使用 $a 对象的 show_one() 函数。
$a->show_one();
?>
强烈建议,如果应用程序序列化对象,以便在应用程序中稍后使用,则应用程序应在整个应用程序中包含该对象的类定义。 不这样做会导致对象被反序列化而没有类定义,这会导致 PHP 为对象分配一个 __PHP_Incomplete_Class_Name 类,该类没有方法,会使对象变得无用。
因此,如果在上面的示例中 $a 通过向 $_SESSION 超全局数组添加一个新键成为会话的一部分,您应该在所有页面上包含文件 A.php
,而不仅仅是 page1.php 和 page2.php。
除了上述建议之外,请注意,您还可以使用 __sleep() 和 __wakeup() 方法挂钩到对象的序列化和反序列化事件。 使用 __sleep() 还允许您仅序列化对象的属性子集。
阅读此页面,你会留下这样的印象,即类的 `serialize` 和 `unserialize` 方法与 `serialize` 和 `unserialize` 核心函数无关;只有 `__sleep` 和 `__unsleep` 允许您自定义对象的序列化接口。 但是看看 https://php.net/manual/en/class.serializable.php,您会发现有一个更直接的方法来控制用户定义的对象是如何序列化和反序列化的。
在这些文档更新之前,请注意,`session_register()` 不需要在会话中自动序列化和反序列化对象。 `$_SESSION` 中的任何对象在会话关闭时(通过 `session_write_close()` 或在脚本退出时)都会被序列化,并在打开时(通过 `session_start()`)被反序列化。 关于在整个应用程序中包含类(通过全局包含定义或自动加载它)的注释仍然有效。
当您需要将对象数据作为文本字符串在脚本和应用程序之间传递时,此技巧很有用。 常见情况包括
* 通过 Web 表单中的字段传递对象
* 在 URL 查询字符串中传递对象
* 将对象数据存储在文本文件中,或存储在单个数据库字段中
并且有时在序列化对象之前进行一些清理很有用。 例如,您可能希望将未保存的对象数据写入数据库并关闭数据库连接。 同样,在反序列化对象后,您可能希望恢复其数据库连接并执行其他设置任务,以便新对象可以正常使用。