下面给你一份 《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; |
| NULL | N; | 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 的区别(常被问)
| 特点 | serialize | json |
|---|---|---|
| 支持对象 | ✔ 是 | ❌ 否(只能数组/标量) |
| 可逆性 | ✔ 强 | ✔ 强 |
| 跨语言兼容性 | ❌ 差 | ✔ 极好 |
| 可读性 | ❌ 不可读 | ✔ 可读 |
👉 跨平台推荐 JSON,存储复杂对象推荐 serialize
#️⃣ 八、serialize 安全问题(必须注意)
unserialize() 历史上爆出过大量安全漏洞。
危险点:
- 反序列化任意对象 → 代码执行漏洞(POP & RCE)
- 攻击者可以构造伪造的序列化字符串触发类的 __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