PHP中的对象序列化:完整指南
序列化是将复杂的数据结构(对象、数组)转换为字符串或二进制格式的过程,以便可以将其保存到文件、通过网络传输或缓存。在PHP中,这一机制通过内置函数serialize()和unserialize()实现。在本文中,我们将详细解析对象序列化的工作原理、存在的陷阱以及如何使用魔术方法对过程进行精细控制。
序列化的基本函数
PHP提供了两个用于处理序列化的关键函数:
serialize($value)— 将值(resource类型除外)转换为适合存储的字符串。对于对象,会保存类名和所有属性(包括私有和受保护的属性)。unserialize($string)— 从字符串中恢复原始值。对于对象,会自动调用类的构造函数(如果已定义)并填入保存的属性。
对象序列化的简单示例
考虑一个基础类User及其序列化:
<?phpclass User { public $name; public $email; private $password;
public function __construct($name, $email, $password) { $this->name = $name; $this->email = $email; $this->password = $password; }}
$user = new User('伊万', 'ivan@example.com', 'secret123');$serialized = serialize($user);echo $serialized;// 输出:O:4:"User":3:{s:4:"name";s:8:"伊万";s:5:"email";s:16:"ivan@example.com";s:12:"\\0User\\0password";s:9:"secret123";}?>请注意:私有属性$password在字符串中显示为\\0User\\0password——这是私有字段的特殊表示法,其中\\0是空字节。
从序列化字符串恢复对象
<?php$serialized = 'O:4:"User":3:{s:4:"name";s:8:"伊万";s:5:"email";s:16:"ivan@example.com";s:12:"\\0User\\0password";s:9:"secret123";}';$user = unserialize($serialized);echo $user->name; // 伊万echo $user->email; // ivan@example.com// 私有属性password也已恢复,但无法直接访问?>重要提示: 反序列化时,如果类尚未定义,PHP会尝试加载该类。如果类不存在,则会创建一个内置类__PHP_Incomplete_Class的实例。
魔术方法 __sleep() 和 __wakeup()
为了控制序列化过程,PHP提供了两个魔术方法:
__sleep()— 在序列化之前调用。应返回一个需要序列化的属性名称数组。适用于关闭数据库连接、释放资源或隐藏敏感数据。__wakeup()— 在反序列化之后立即调用。用于重新连接数据库、恢复资源或检查数据完整性。
__sleep() 和 __wakeup() 示例
<?phpclass DatabaseConnection { private $host; private $user; private $password; private $connection;
public function __construct($host, $user, $password) { $this->host = $host; $this->user = $user; $this->password = $password; $this->connect(); }
private function connect() { // 模拟连接 $this->connection = "连接到 {$this->host} 的资源"; }
public function __sleep() { // 不序列化连接资源,只序列化用于重新连接的数据 return ['host', 'user', 'password']; }
public function __wakeup() { // 恢复连