frodeborli/serializor

PHP Serializor 可以将几乎所有内容序列化,包括闭包和匿名类。

v1.0.2 2024-09-07 04:31 UTC

This package is auto-updated.

Last update: 2024-09-11 18:55:05 UTC


README

Serializor 是一个先进的 PHP 序列化库,旨在简化闭包、匿名类和复杂数据结构的序列化。它能够无缝处理其他库可能难以应对的场景,而无需对现有代码进行修改。无论是用于分布式计算、对象缓存还是作业队列,Serializor 都能确保复杂数据类型在序列化和反序列化过程中完美保留其行为和状态。

Serializor 支持的高级用例

Serializor 设计用于处理一系列复杂的序列化场景,这些场景其他库可能无法有效支持。这种能力确保开发人员可以无缝地管理复杂的数据结构,尤其是在数据完整性和真实性至关重要的环境中。以下是 Serializor 突出的几个关键场景:

1. 带上下文闭包的序列化

Serializor 在序列化闭包方面表现出色,包括带有绑定上下文和作用域变量的闭包。与一些仅将闭包转换为可序列化表示并需要手动恢复的库不同,Serializor 自动序列化和恢复闭包,包括任何上下文或 use 变量,使其恢复到功能状态。

支持的场景:

  • 序列化一个修改捕获变量的闭包,确保在反序列化后,闭包和变量的状态都得到准确恢复。

2. 处理只读和类型属性

PHP 8.1 引入了只读属性,这些属性在初始化后不能被修改。Serializor 可以序列化和反序列化具有只读属性的对象,而不会改变其状态,这是其他序列化库所不支持的功能。

支持的场景:

  • 利用 PHP 8.1 的只读属性的对象,确保这些属性在反序列化后得到正确处理且未被更改。

3. 复杂递归结构

Serializor 可以序列化和反序列化深度嵌套或递归结构,而不会遇到递归限制或丢失引用。这对于处理必须准确维护引用的复杂数据模型的应用程序特别重要。

支持的场景:

  • 序列化一个由多个对象相互引用的复杂对象图,在序列化过程中保持准确的链接和标识。

4. 带有动态属性的对象

Serializor 支持在运行时动态分配属性的对象。它确保序列化和恢复所有属性,即使是那些在类中未静态定义的属性。

支持的场景:

  • 序列化实现 __get__set 等魔术方法的对象,捕获所有动态分配的属性。

5. 闭包绑定和作用域

Serializor 提供了对绑定到特定对象实例或类的闭包的强大支持,在序列化和反序列化过程中准确地尊重它们的范围和上下文。

支持的场景:

  • 序列化绑定到特定对象实例的闭包,确保在反序列化后,闭包继续在正确的范围内运行,并保留对绑定对象的方法和属性的访问。

6. 安全功能

借助内置的安全功能,如 HMAC 签名,Serializor 确保序列化数据未遭到篡改。这对于在不太安全的渠道上序列化数据或长期存储序列化数据的应用程序至关重要。

支持的场景:

  • 序列化需要安全地在应用程序的不同部分之间传输或在安全方式下存储的敏感信息,使用 HMAC 签名在反序列化时验证数据完整性。

7. 复杂序列化转换器

Serializor 允许开发者通过自定义转换器扩展其功能,通过将对象转换为可存储的格式并返回,使其能够序列化原本不可序列化的对象。

支持的场景:

  • 通过实现自定义转换器,处理资源或数据库连接句柄的特定要求和细微差别,来实现对这些类型的序列化。

支持更复杂的结构

Serializor 不依赖于封装闭包。您可以直接序列化和反序列化闭包,例如,如果您的闭包存储在对象的只读属性中。

$data = $serializor->serialize(function() {});
$func = $serializor->unserialize($data);

性能

Serializor 在性能上显著优于 opis/closure 和 laravel/serializable-closure,同时功能更强大。

序列化性能

Serializor 的速度比 Opis/Closure 快一个数量级。在反序列化方面略慢,但在序列化方面速度更快——足以弥补较慢的反序列化速度。

Serialization

Unserialization

功能

  • 无需修改即可序列化闭包:Serializor 可以序列化任何闭包,即使它存储在类型为只读属性的属性中(例如,public readonly Closure $prop),也不需要将闭包包装在特殊的类型如 SerializableClosure 中。

  • 支持类型化的只读属性:无需更改属性类型或围绕特殊类结构您的代码来序列化闭包。Serializor 可以在保持与 PHP 类型系统兼容性的同时序列化和反序列化闭包,包括只读属性。

  • 匿名类的序列化:Serializor 支持序列化匿名类。虽然反序列化的类可能不会完全相同,但它将保留结构和功能,在大多数情况下非常可用。

  • 高效且安全:Serializor 使用机器特定的密钥来确保在某个机器上序列化的数据可以在同一机器上正确地反序列化,使库在系统重启后保持安全和一致。

安装

composer require frodeborli/serializor

基本用法

Serializor 被设计为无缝替换 PHP 的原生 serialize()unserialize() 函数。以下是您如何使用它的方法

闭包的序列化

$closure = function () {
    return 'Hello from closure!';
};

$serialized = Serializor::serialize($closure);
$unserializedClosure = Serializor::unserialize($serialized);

// Execute the closure
echo $unserializedClosure(); // Output: Hello from closure!

序列化类型化的只读属性

Serializor 无需修改即可处理类型化的只读属性

class MyClass {
    public readonly Closure $myClosure;

    public function __construct() {
        $this->myClosure = function() {
            return 'I am serialized!';
        };
    }
}

$instance = new MyClass();
$serialized = Serializor::serialize($instance);
$unserializedInstance = Serializor::unserialize($serialized);

echo $unserializedInstance->myClosure(); // Output: I am serialized!

序列化匿名类

Serializor 支持序列化匿名类

$anonClass = new class {
    public function sayHello() {
        return 'Hello from anonymous class!';
    }
};

$serialized = Serializor::serialize($anonClass);
$unserializedClass = Serializor::unserialize($serialized);

echo $unserializedClass->sayHello(); // Output: Hello from anonymous class!

与其他方法的比较

许多序列化库需要您将闭包包裹在特殊类型中,如 Opis\ClosureSerializableClosure。这通常会导致以下问题

  1. 修改类结构:您被迫更改类中的属性类型以支持 ClosureSerializableClosure。例如

    public Closure|SerializableClosure $myClosure;

    这使您的代码变得复杂,并需要您在整个代码库中调整类型。

  2. 类型化的只读属性:如 Opis\Closure 这样的库不原生处理类型化的只读属性,特别是严格的类型 public readonly Closure $prop。您可能需要删除类型提示或将其更改为更灵活的类型。

  3. 额外的样板代码:将闭包包裹在特殊类如 SerializableClosure 中会增加不必要的样板代码,并降低代码的可读性。

Serializor 解决了这些问题

  • 无需更改类型:使用 Serializor,无需修改属性类型或添加对 SerializableClosure 的支持。您可以直接序列化存储在 Closure 类型属性中的闭包,而无需更改类设计。

  • 类型化的只读属性:Serializor 支持 public readonly Closure $prop,而不会破坏类型系统或需要您调整属性类型。

  • 匿名类:Serializor默认支持匿名类的序列化,但反序列化会创建一个功能相似但并非完全相同的类。在许多情况下,只要类的行为保持不变,这种差异是可以忽略不计的。

机器特定的密钥

为了安全,Serializor通过检查某些系统文件生成机器特定的密钥。这确保了在相同的机器上序列化和反序列化工作的一致性,但不会允许在不同机器上进行反序列化。如果您需要跨机器序列化,您可以设置自定义密钥。

Serializor::setDefaultSecret('your-custom-secret');

注意事项

  • 匿名类:在序列化匿名类时,反序列化的类将与原始类相似但不完全相同——它们不是同一类型。在大多数使用场景中,这不应该是一个问题,但请注意这个限制。

性能和安全

Serializor旨在既快又安全。通过利用机器特定的密钥,它避免了与PHP序列化相关的大多数常见安全陷阱。该库已针对闭包、匿名类和复杂对象图进行了优化,以有效地处理。

许可证

此库是开源的,可在MIT许可证下使用。