PHP 对象序列化:从基础到高级技巧
序列化是将复杂数据结构(对象、数组)转换为适合存储或传输的线性格式的过程。在 PHP 中,这一机制对于在请求之间保存对象状态、通过 API 传输数据或写入数据库尤为重要。本文将详细解析 PHP 中序列化的各个方面。
什么是序列化,为什么需要它?
序列化允许将对象“冻结”为字符串,然后再恢复回来。这在以下场景中非常有用:
- 保存用户会话(PHP 会自动序列化会话数据)
- 在 Redis 或 Memcached 中缓存复杂对象
- 在微服务之间传输对象
- 将配置存储在文件中
- 调试和记录对象状态
基本序列化:serialize() 和 unserialize()
PHP 提供了两个主要函数用于处理序列化:
<?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:15:"伊万·彼得罗夫";s:5:"email";s:16:"ivan@example.com";s:14:"\\0User\\0password";s:9:"secret123";}
// 恢复对象$unserialized = unserialize($serialized);echo $unserialized->name; // 伊万·彼得罗夫?>重要提示: serialize() 函数会处理对象的所有属性,包括私有和受保护的属性。私有属性以 \\0ClassName\\0 为前缀编码,受保护属性以 \\0*\\0 为前缀编码。
魔术方法 __sleep() 和 __wakeup()
为了控制序列化过程,PHP 提供了两个魔术方法:
- __sleep() — 在序列化之前调用。应返回需要序列化的属性名称数组。
- __wakeup() — 在反序列化之后调用。用于重新初始化资源(例如数据库连接)。
<?phpclass DatabaseConnection { private $connection; private $dsn; private $username; private $password; private $cache = [];
public function __construct($dsn, $username, $password) { $this->dsn = $dsn; $this->username = $username; $this->password = $password; $this->connect(); }
private function connect() { // 模拟数据库连接 $this->connection = new stdClass(); $this->connection->connected = true; }
public function __sleep() { // 不序列化连接资源和密码 return ['dsn', 'username', 'cache']; }
public function __wakeup() { // 反序列化后恢复连接 $this->connect(); }}
$db = new DatabaseConnection('mysql:host=localhost;dbname=test', 'root', 'pass');$serialized = serialize($db);$restored = unserialize($serialized);?>JSON 序列化:json_encode() 和 json_decode()
JSON 是一种更通用的格式,被许多编程语言支持。在 PHP 中,使用 json_encode() 和 json_decode() 函数进行 JSON 序列化。
<?phpclass Product { public $id; public $name; public $price;
public function __construct($id, $name, $price) { $this->id = $id; $this->name = $name; $this->price = $price; }}
$product