serialize

(PHP 4, PHP 5, PHP 7, PHP 8)

serialize生成值的可存储表示

描述

serialize(混合 $value): 字符串

生成值的可存储表示。

这对于在不丢失其类型和结构的情况下存储或传递 PHP 值很有用。

要将序列化字符串重新转换为 PHP 值,请使用 unserialize()

参数

value

要序列化的值。 serialize() 处理所有类型,除了 资源 类型和一些 对象(见下文说明)。你甚至可以 serialize() 包含对自身引用的数组。序列化数组/对象内部的循环引用也将被存储。任何其他引用都将丢失。

序列化对象时,PHP 会尝试在序列化之前调用成员函数 __serialize()__sleep()。这样做是为了允许对象在被序列化之前进行任何最后时刻的清理等。同样,当对象使用 unserialize() 恢复时,会调用 __unserialize()__wakeup() 成员函数。

说明:

对象的私有成员在成员名前面加上类名;受保护的成员在成员名前面加上 '*'. 这些前缀值的两侧都有空字节。

返回值

返回一个包含 value 的字节流表示的字符串,该字符串可以存储在任何地方。

请注意,这是一个二进制字符串,可能包含空字节,需要以这种方式存储和处理。例如,serialize() 输出通常应存储在数据库中的 BLOB 字段中,而不是 CHAR 或 TEXT 字段中。

示例

示例 #1 serialize() 示例

<?php
// $session_data 包含一个多维数组,其中包含当前用户的会话
// 信息。我们在请求结束时使用 serialize() 将其存储在数据库中。

$conn = odbc_connect("webdb", "php", "chicken");
$stmt = odbc_prepare($conn,
"UPDATE sessions SET data = ? WHERE id = ?");
$sqldata = array (serialize($session_data), $_SERVER['PHP_AUTH_USER']);
if (!
odbc_execute($stmt, $sqldata)) {
$stmt = odbc_prepare($conn,
"INSERT INTO sessions (id, data) VALUES(?, ?)");
if (!
odbc_execute($stmt, array_reverse($sqldata))) {
/* 出现了一些错误.. */
}
}
?>

说明

说明:

请注意,许多内置 PHP 对象无法序列化。但是,那些具有此功能的对象要么实现了 Serializable 接口,要么实现了魔法 __serialize()/__unserialize()__sleep()/__wakeup() 方法。如果内部类没有满足任何这些要求,则无法可靠地对其进行序列化。

对于上述规则,有一些历史上的例外情况,其中一些内部对象可以在没有实现接口或公开方法的情况下进行序列化。

警告

serialize() 序列化对象时,为了最大程度的兼容性,命名空间类的类名中不包括前导反斜杠。

参见

添加说明

用户贡献说明 7 条说明

358
egingell at sisna dot com
18 年前
<?
/*
序列化值的结构

字符串
s:size:value;

整数
i:value;

布尔值
b:value;(不存储 "true" 或 "false",存储 '1' 或 '0')


N;

数组
a:size:{键定义;值定义;(每个元素重复)}

对象
O:strlen(对象名称):对象名称:对象大小:{s:strlen(属性名称):属性名称:属性定义;(每个属性重复)}

字符串值始终用双引号括起来
数组键始终是整数或字符串
"null => 'value'" 等效于 's:0:"";s:5:"value";',
"true => 'value'" 等效于 'i:1;s:5:"value";',
"false => 'value'" 等效于 'i:0;s:5:"value";',
"array(无论内容) => 'value'" 等效于 "非法偏移类型" 警告,因为你无法使用
数组作为键;但是,如果使用包含数组的变量作为键,它将等效于 's:5:"Array";s:5:"value";',
并且
尝试使用对象作为键会导致与使用数组相同的行为。
*/
?>
279
匿名
12 年前
请!请!请!不要序列化数据并将其放入你的数据库中。序列化可以这样使用,但这忽略了关系数据库和你的数据库引擎中固有数据类型的意义。这样做会使你的数据库中的数据不可移植,难以读取,并会使查询复杂化。如果你希望你的应用程序能够移植到其他语言,比如你发现你想要在你的应用程序的某些部分使用 Java(在使用 Java 更合适的地方),序列化就会变得很麻烦。你应该始终能够在不使用第三方中间工具来操作要插入的数据的情况下查询和修改数据库中的数据。

我在我的职业生涯中遇到过这种情况很多次,它会导致难以维护的代码、存在可移植性问题的代码以及更难以迁移到其他 RDMS 系统、新模式等的数据。它还具有使根据你已序列化的字段之一搜索你的数据库变得很麻烦的额外缺点。

这并不是说 serialize() 无用。它并非如此... 一个使用它的好地方可能是包含数据密集型操作结果的缓存文件,例如。还有很多其他地方... 只是不要滥用 serialize(),因为下一个接手的人将会遇到维护或迁移的噩梦。
2
mark at bvits dot co dot uk
1 年前
在用户说明中尚未提及的一种类型是 'E'。这是可以使用的较新的 Enum 类

login_security|E:25:"Permission:manageClient"
21
MC_Gurk at gmx dot net
18 年前
如果你要序列化包含对其他对象的引用的对象,并且你想要稍后序列化这些对象,那么当对象被反序列化时,这些引用将会丢失。
只有当你一次序列化所有对象时,才能保留这些引用。
这意味着

$a = new ClassA();
$b = new ClassB($a); //$b 包含对 $a 的引用;

$s1=serialize($a);
$s2=serialize($b);

$a=unserialize($s1);
$b=unserialize($s2);

现在,b 对 ClassA 的对象的引用不是 $a。$a 是 Class A 的另一个对象。

使用这个
$buf[0]=$a;
$buf[1]=$b;
$s=serialize($buf);
$buf=unserialize($s);
$a=$buf[0];
$b=$buf[1];

所有引用都完好无损。
25
nh at ngin dot de
11 年前
序列化浮点数会导致奇怪的精度偏移错误

<?php

echo round(96.670000000000002, 2);
// 96.67

echo serialize(round(96.670000000000002, 2));
// d:96.670000000000002;

echo serialize(96.67);
// d:96.670000000000002;

?>

这不仅是错误的,而且还会给序列化数据增加大量不必要的体积。也许使用 json_encode() 更好(据说是比 serialize() 更快)。
13
frost at easycast dot ru
10 年前
闭包无法序列化
<?php
$func
= function () {echo 'hello!';};
$func(); // 打印 "hello!"

$result = serialize($func); // 致命错误:未捕获的异常 'Exception',消息为 'Serialization of 'Closure' is not allowed'
?>
9
Andrew B
11 年前
当您序列化数组时,内部指针将不会被保留。显然这是预期的行为,但对我来说是一个小问题。请复制粘贴下面的示例。

<?php
// 在变量被赋值后,内部指针将为 2。
$array = array();
$array[] = 1;
$array[] = 2;
$array[] = 3;

// 取消设置变量。内部指针将仍然停留在 2。
unset($array[0]);
unset(
$array[1]);
unset(
$array[2]);

// 序列化
$serializeArray = serialize($array);

// 反序列化
$array = unserialize($serializeArray);

// 向数组添加一个新元素
// 如果内部指针被保留,新数组的键应该为 3。
// 但是内部指针被重置,新数组的键为 0。
$array[] = 4;

// 预期的键 - 3
// 实际键 - 0
echo "<pre>" , print_r($array, 1) , "</pre>";
?>
To Top