
PHP中serialize()和unserialize()的基本用法
PHP原生序列化靠serialize()把变量转成字符串,靠unserialize()还原。它支持数组、对象、整数、字符串等,但不支持资源(如fopen()返回的句柄)和闭包——直接调用会报Fatal error: Uncaught Exception: Serialization of 'Closure' is not allowed。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 对象序列化前确保类已定义,否则
unserialize()时会生成__PHP_Incomplete_Class对象,属性不可访问 - 若变量含大量嵌套或递归引用,
serialize()可能触发memory_limit超限,需提前检查ini_get('memory_limit') -
serialize()结果是ASCII安全的,可直接存数据库或写文件,但别直接输出到HTML,避免意外解析(比如O:8:"stdClass":1:{s:3:"foo";s:3:"bar";}里的冒号、花括号)
对象序列化时__sleep()和__wakeup()的作用
这两个魔术方法不是可选装饰,而是控制序列化行为的关键开关。没有__sleep(),PHP默认序列化所有public/protected/private属性;加了它,就必须返回一个字符串数组,指定哪些属性参与序列化——漏写会导致数据丢失,多写不存在的属性名则抛E_NOTICE。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
-
__sleep()里不能调用$this上的方法(因对象可能处于不稳定状态),常见错误是误写$this->closeConnection()导致序列化失败 -
__wakeup()常用于重建资源(如重连数据库),但它在unserialize()后立即执行,此时构造函数尚未运行,别依赖$this->init()这类逻辑 - 如果类有静态属性,它们不会被序列化,
__wakeup()里也不能恢复——这是设计限制,不是bug
为什么unserialize()是高危操作?
因为反序列化过程会触发对象创建和魔术方法调用,攻击者只要控制输入字符串,就能诱导执行任意代码。典型漏洞链是:传入恶意字符串 → unserialize() → 触发__wakeup()或__destruct() → 调用危险方法(如system()、file_put_contents())。
Perl 基础入门中文教程,chm格式,讲述PERL概述、简单变量、操作符、列表和数组变量、文件读写、模式匹配、控制结构、子程序、关联数组/哈希表、格式化输出、文件系统、引用、面向对象、包和模块等知识点。适合初学者阅读和了解Perl脚本语言。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 绝对不要对用户可控输入(如
$_GET['data']、cookie值)调用unserialize() - PHP 7.4+ 可配合
unserialize($data, ['allowed_classes' => false])禁用对象反序列化,只允许基础类型 - 更稳妥的替代方案是改用
json_encode()/json_decode(),它天然不支持对象和资源,且无执行风险
序列化与JSON互换的边界在哪?
json_encode()不能替代serialize()处理所有场景,核心差异在类型保真度:serialize()能区分null、0、false、空字符串,而JSON会把null和false都变成false(当JSON_FORCE_OBJECT未启用时);更关键的是,JSON无法保留PHP的类型信息,比如array(1,2,3)和(object)[1,2,3]经json_encode()后都是[1,2,3],json_decode()默认只返回stdClass对象。
实操建议:
立即学习“PHP免费学习笔记(深入)”;
- 跨语言传输(如PHP ↔ JS)必须用JSON;仅PHP内部存储/缓存可用
serialize() - 用
json_decode($json, true)强制返回数组,避免后续写isset($obj->key)出错 - 含中文的字符串务必确认
mb_internal_encoding()为UTF-8,否则json_encode()可能返回null
真正麻烦的从来不是“怎么序列化”,而是“谁在反序列化”和“反序列化后谁在调用”。只要输入来源不可信,unserialize()就等于主动打开门锁。










