PHP 怎么再水化

wen PHP项目 5

本文目录导读:

PHP 怎么再水化

  1. 使用 unserialize()(最常见于 Session 和缓存)
  2. 使用 json_decode()(推荐的安全方式)
  3. 数据库 ORM(Doctrine / Eloquent)的 Hydration
  4. 自定义映射(手动再水化)
  5. 使用 Hydrator 库(企业级应用)
  6. 总结:选择哪种方式?
  7. ⚠️ 重要安全提示

在 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 HydratorSymfony 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 库。

⚠️ 重要安全提示

再水化过程中,请务必验证数据的安全性:

  1. 不要对不可信数据使用 unserialize(),防止对象注入攻击。
  2. 使用 Data Transfer Objects (DTO)Property Mapping 来确保只允许期望的字段被赋值。
  3. 对于数据库查询,使用 预处理语句(Prepared Statements) 防止 SQL 注入。

如果你在 Laravel 或 Symfony 中有特定的再水化需求,可以告诉我具体框架,我可以给出更针对性的代码示例。

抱歉,评论功能暂时关闭!