下面给你一份 《PHP serialize 序列化工作的完全指南》 ——从基础到高级、兼容性、安全性、调试、性能、最佳实践全覆盖,适合做项目、写接口、调 API 的环境。


#️⃣ 一、什么是 serialize?

serialize() 是 PHP 内置函数,用于把 变量(数组、对象等)转换成一个可存储、可传输的字符串
常用于:

  • 写入数据库
  • 写入文件
  • Redis 缓存
  • Cookie / Session 存储
  • RPC/远程请求
  • 队列系统

👉 反序列化用 unserialize()


#️⃣ 二、serialize() 的语法与示例

$serialized = serialize($data);
$original = unserialize($serialized);

示例:

$array = ["name" => "Jack", "age" => 20];
echo serialize($array);

输出:

a:2:{s:4:"name";s:4:"Jack";s:3:"age";i:20;}


#️⃣ 三、PHP 序列化字符串格式规则(非常重要)

PHP serialize 输出的字符串遵循固定格式:

类型标记示例
整型 (integer)i:i:123;
浮点数 (double)d:d:3.14;
字符串 (string)s:length:"xxxxx";s:5:"hello";
布尔 (boolean)b:b:1;
NULLN;N;
数组a:length:{...}a:2:{...}
对象O:length:"Class":props:{...}O:4:"User":2:{...}

#️⃣ 四、序列化数组示例(最常用)

$data = [
    "title" => "hello",
    "count" => 100,
];

echo serialize($data);

输出:

a:2:{s:5:"title";s:5:"hello";s:5:"count";i:100;}


#️⃣ 五、序列化对象(O:…)示例

class User {
    public $name = "Tom";
    public $age = 30;
}
$obj = new User();

echo serialize($obj);

输出格式:

O:4:"User":2:{s:4:"name";s:3:"Tom";s:3:"age";i:30;}


#️⃣ 六、对象反序列化时常见问题(反序列化失败)

1. 类不存在(报 Notice)

如果 unserialize 时 PHP 找不到类,会导致属性丢失:

unserialize('O:4:"User":1:{s:4:"name";s:3:"Tom";}');

解决:

require "User.php";

或使用:

unserialize($data, ["allowed_classes" => true]);


#️⃣ 七、serialize 与 JSON 的区别(常被问)

特点serializejson
支持对象✔ 是❌ 否(只能数组/标量)
可逆性✔ 强✔ 强
跨语言兼容性❌ 差✔ 极好
可读性❌ 不可读✔ 可读

👉 跨平台推荐 JSON,存储复杂对象推荐 serialize


#️⃣ 八、serialize 安全问题(必须注意)

unserialize() 历史上爆出过大量安全漏洞

危险点:

  1. 反序列化任意对象 → 代码执行漏洞(POP & RCE)
  2. 攻击者可以构造伪造的序列化字符串触发类的 __wakeup() 或 __destruct()

安全使用方式:

unserialize($data, ["allowed_classes" => false]);

或指定白名单:

unserialize($data, ["allowed_classes" => ["User"]]);

⚠️ 绝对不要反序列化用户提交的数据。


#️⃣ 九、序列化字符串长度错误的常见原因

PHP 对字符串使用:

s:length:"value";

如果 length 与实际内容不一致,会报错或截断:

例如(错误):

s:4:"hello";

实际 hello 长度是 5,会解析失败。

常见原因:

  • 手动修改数据
  • 数据库字段编码不一致(如 utf8mb4)
  • 数据被转义(addslashes)

解决方法:

  • 使用 BLOB,而不是 TEXT
  • 禁止修改序列化字符串
  • 保证无转义

#️⃣ 十、serialize 的替代方案

避免安全问题和兼容性问题,推荐:

✔ JSON:轻量、跨语言、最常用

json_encode($data)

✔ igbinary(扩展):更快更小

igbinary_serialize($data);


#️⃣ 十一、serialize 调试技巧

查看序列化内容美化后的结构:

$data = unserialize($str);
var_dump($data);

也可用在线工具(更直观):

PHP serialize viewer


#️⃣ 十二、serialize 最佳实践(总结)

✔ 用 serialize 存仅限 PHP 内部使用的数据(session、cache、队列)
✔ 存数据库用 BLOB
✔ 绝不反序列化用户输入
✔ 对象反序列化时必须加载类
✔ 跨平台数据用 JSON
✔ 需要压缩可用 gzcompress + serialize