PHP Conference Japan 2024

序列化对象 - 会话中的对象

serialize() 返回一个字符串,其中包含可以存储在 PHP 中的任何值的字节流表示形式。unserialize() 可以使用此字符串重新创建原始变量值。使用 serialize 保存对象将保存对象中的所有变量。对象中的方法不会被保存,只有类的名称。

为了能够 unserialize() 一个对象,需要定义该对象的类。也就是说,如果您有一个类 A 的对象并对其进行序列化,您将得到一个引用类 A 并包含其中包含的所有变量值的字符串。如果您想能够在另一个文件中反序列化它,类 A 的对象,类 A 的定义必须首先存在于该文件中。这可以通过例如将类 A 的类定义存储在 include 文件中并包含此文件或使用 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.phppage2.php

除了以上建议之外,请注意,您还可以使用 __sleep()__wakeup() 方法挂接到对象的序列化和反序列化事件。使用 __sleep() 还允许您仅序列化对象属性的子集。

添加注释

用户贡献的注释 3 条注释

235
php at lanar dot com dot au
15 年前
请注意,对象的静态成员不会被序列化。
34
michael at smith-li dot com
9 年前
阅读此页面,您会留下这样的印象:类的 `serialize` 和 `unserialize` 方法与 `serialize` 和 `unserialize` 核心函数无关;只有 `__sleep` 和 `__unsleep` 允许您自定义对象的序列化接口。但请查看 https://php.net/manual/en/class.serializable.php,您会发现有一种更直接的方法来控制用户定义的对象是如何序列化和反序列化的。
8
匿名用户
3 年前
在这些文档更新之前,请注意,`session_register()` 不需要自动在会话中序列化和反序列化对象。`$_SESSION` 中的任何对象在会话关闭时(通过 `session_write_close()` 或在脚本退出时)都会被序列化,并在打开时(通过 `session_start()`)被反序列化。关于在整个应用程序中包含类(通过全局包含定义或自动加载它)的注释仍然有效。
To Top