本文目录导读:

- 使用
unserialize()(最常见于 Session 和缓存) - 使用
json_decode()(推荐的安全方式) - 数据库 ORM(Doctrine / Eloquent)的 Hydration
- 自定义映射(手动再水化)
- 使用 Hydrator 库(企业级应用)
- 总结:选择哪种方式?
- ⚠️ 重要安全提示
在 PHP 中,“再水化”(Rehydration)通常指的是将存储在数据库、缓存或序列化格式中的数据,重新转换回PHP 对象的过程,这是与“水化”(Hydration,将对象转为数组/存储格式)相反的操作。
以下是 PHP 中实现再水化的几种常见场景和具体方法:
使用 unserialize()(最常见于 Session 和缓存)
如果你之前使用 serialize() 将对象或数组保存到了文件、数据库或缓存中,再水化就是使用 unserialize()。
<?php
// 假设我们从数据库或缓存中取出了这个字符串
$stored_data = 'O:8:"stdClass":2:{s:4:"name";s:5:"Alice";s:3:"age";i:30;}';
$object = unserialize($stored_data);
// 使用再水化后的对象
echo $object->name; // 输出 Alice
注意(安全警告): 永远不要对来自用户输入或不可信来源的数据使用 unserialize(),这会导致 PHP 对象注入(严重安全漏洞),建议使用 json_encode / json_decode 作为安全的替代方案。
使用 json_decode()(推荐的安全方式)
将 JSON 字符串再水化为 PHP 对象或数组。
<?php
$json = '{"id": 1, "title": "Hello World", "published": true}';
// 第二个参数 false 返回对象(默认),true 返回关联数组
$post = json_decode($json);
echo $post->title; // 输出 Hello World
// 如果需要转换成自定义的业务类,需要手动映射:
class Post {
public int $id;
public string $title;
}
$post_obj = new Post();
$post_obj->id = $post->id;
$post_obj->title = $post->title;
数据库 ORM(Doctrine / Eloquent)的 Hydration
在使用 Laravel(Eloquent)或 Symfony(Doctrine)时,再水化通常由框架自动完成。
// Laravel Eloquent 示例
$user = User::find(1);
// 这一行内部就是从数据库结果集中的数组,再水化成一个 User 对象。
// 或者使用模型工厂
$user = User::hydrate([
['id' => 1, 'name' => 'John'],
['id' => 2, 'name' => 'Jane'],
]);
如果你是手写 PDO,需要手动进行再水化:
<?php
$pdo = new PDO('mysql:host=localhost;dbname=test', 'user', 'pass');
$stmt = $pdo->query("SELECT * FROM users WHERE id = 1");
$stmt->setFetchMode(PDO::FETCH_CLASS, 'App\Models\User'); // 关键步骤
$user = $stmt->fetch(); // $user 现在是一个 User 对象
自定义映射(手动再水化)
当数据结构不匹配时,需要手动赋值:
<?php
class UserAccount {
public string $full_name;
public string $email_address;
}
$raw_data = [
'name' => 'John Doe',
'email' => 'john@example.com'
];
$account = new UserAccount();
// 手动映射(再水化)
$account->full_name = $raw_data['name'];
$account->email_address = $raw_data['email'];
使用 Hydrator 库(企业级应用)
如果你使用 Laminas Hydrator 或 Symfony Serializer,可以自动处理数组到对象的映射:
// Symfony Serializer 示例
use Symfony\Component\Serializer\Serializer;
use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$data = '{"name": "Alice", "age": 30}';
$user = $serializer->deserialize($data, User::class, 'json');
// 自动将 JSON 再水化为 User 对象
选择哪种方式?
- 如果数据是 JSON:使用
json_decode()(建议)。 - 如果数据是 PHP 序列化格式:使用
unserialize()(需确保数据可信)。 - 如果使用框架(Laravel/Symfony):直接用框架自带的 ORM 功能。
- 如果从数据库取出:配置
PDO::FETCH_CLASS或使用 Hydrator 库。
⚠️ 重要安全提示
再水化过程中,请务必验证数据的安全性:
- 不要对不可信数据使用
unserialize(),防止对象注入攻击。 - 使用 Data Transfer Objects (DTO) 加 Property Mapping 来确保只允许期望的字段被赋值。
- 对于数据库查询,使用 预处理语句(Prepared Statements) 防止 SQL 注入。
如果你在 Laravel 或 Symfony 中有特定的再水化需求,可以告诉我具体框架,我可以给出更针对性的代码示例。