# PHP序列化与反序列化:serialize()和unserialize()详解
在PHP开发中,我们经常需要将复杂的数据结构(如数组、对象等)转换为字符串形式进行存储或传输,这时就需要用到序列化和反序列化操作。本文将深入讲解PHP中的serialize()和unserialize()函数的使用方法和注意事项。
## 一、什么是序列化和反序列化?
**序列化(serialize)**是将PHP变量(如数组、对象)转换为可存储或传输的字符串表示的过程。
**反序列化(unserialize)**则是将序列化后的字符串重新转换为PHP变量的过程。
## 二、serialize()函数详解
### 基本用法
```php
$data = ['name' => '张三', 'age' => 25, 'is_student' => true];
$serialized = serialize($data);
echo $serialized;
// 输出类似:a:3:{s:4:"name";s:6:"张三";s:3:"age";i:25;s:9:"is_student";b:1;}
```
### 序列化格式说明
序列化后的字符串包含数据类型和值的结构化表示:
- `a` - 数组(array)
- `s` - 字符串(string)
- `i` - 整数(integer)
- `b` - 布尔值(boolean)
- `d` - 双精度浮点数(double)
- `O` - 对象(object)
- `N` - NULL
### 对象序列化示例
```php
class User {
public $name;
private $age;
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
}
$user = new User('李四', 30);
echo serialize($user);
// 输出类似:O:4:"User":2:{s:4:"name";s:6:"李四";s:9:"Userage";i:30;}
```
## 三、unserialize()函数详解
### 基本用法
```php
$serialized = 'a:3:{s:4:"name";s:6:"张三";s:3:"age";i:25;s:9:"is_student";b:1;}';
$data = unserialize($serialized);
print_r($data);
/*
输出:
Array
(
[name] => 张三
[age] => 25
[is_student] => 1
)
*/
```
### 对象反序列化
```php
$serialized = 'O:4:"User":2:{s:4:"name";s:6:"李四";s:9:"Userage";i:30;}';
$user = unserialize($serialized);
echo $user->name; // 输出:李四
```
## 四、应用场景
1. **数据存储**:将复杂数据结构存入数据库或文件
2. **会话存储**:PHP默认使用序列化存储会话数据
3. **缓存系统**:如Memcached、Redis等
4. **API通信**:在网络传输前序列化数据
## 五、注意事项
### 1. 安全风险
反序列化操作可能存在安全风险,特别是当处理用户提供的序列化数据时。恶意构造的序列化字符串可能导致代码执行。
**安全建议**:
- 不要反序列化不可信来源的数据
- 使用json_encode()/json_decode()处理简单数据(JSON更安全)
- 实现__wakeup()和__sleep()魔术方法时注意安全性
### 2. 对象反序列化要求
- 类必须在反序列化前已定义
- 如果类定义发生变化,可能导致反序列化失败
### 3. 性能考虑
序列化和反序列化是CPU密集型操作,大数据量时可能影响性能。
## 六、魔术方法相关
PHP提供了一些魔术方法来自定义序列化行为:
- `__sleep()`:在序列化时调用,返回需要序列化的属性名数组
- `__wakeup()`:在反序列化时调用,用于重新建立资源连接等
- `__serialize()`:PHP 7.4+,替代__sleep()提供更灵活的序列化控制
- `__unserialize()`:PHP 7.4+,替代__wakeup()
示例:
```php
class User {
private $password;
public function __sleep() {
// 不序列化password字段
return ['name', 'age'];
}
public function __wakeup() {
// 反序列化后重新初始化某些状态
$this->loggedIn = false;
}
}
```
## 七、替代方案:JSON
对于简单数据结构,可以考虑使用JSON:
```php
// 序列化
$json = json_encode($data);
// 反序列化
$data = json_decode($json, true); // true表示返回数组而非对象
```
**JSON vs 序列化**:
- JSON更安全,但只能处理简单数据类型
- 序列化能处理复杂对象,但存在安全风险
- JSON可跨语言使用,序列化是PHP特有的
## 结语
PHP的序列化和反序列化功能强大但需谨慎使用。在实际开发中,应根据具体需求选择合适的序列化方式,并始终将安全性放在首位。对于对象序列化,合理使用魔术方法可以更好地控制序列化过程。