frodeborli/serializor

PHP Serializor will serialize almost anything in PHP, including closures and anonymous classes.

Installs: 142

Dependents: 0

Suggesters: 0

Security: 0

Stars: 19

Watchers: 2

Forks: 3

Open Issues: 0

pkg:composer/frodeborli/serializor

v2.1.0 2025-12-30 09:12 UTC

This package is auto-updated.

Last update: 2025-12-30 22:49:29 UTC


README

Tests Packagist PHP Version Downloads License

Serialize closures and anonymous classes

Serializor is a PHP library that allows you to serialize closures, anonymous classes, and arbitrary data - without wrapper classes or code modifications.

Key features:

  • serialize closures without wrapper classes
  • serialize anonymous classes
  • works with readonly properties - no __serialize() required
  • works with typed Closure properties (public readonly Closure $handler)
  • handles circular and recursive references
  • supports WeakReference and WeakMap with correct weak semantics
  • supports SPL classes (ArrayObject, SplObjectStorage, SplDoublyLinkedList, etc.)
  • supports DateTime classes
  • extensible via custom transformers
  • optional HMAC signing for secure cross-machine serialization
  • does not rely on PHP extensions (no FFI or similar dependencies)
  • supports PHP 8.2 - 8.5

Example: Closure serialization

use Serializor\Serializor;

$greet = fn($name) => "Hello, $name!";

$serialized = Serializor::serialize($greet);
$restored = Serializor::unserialize($serialized);

echo $restored('World'); // Hello, World!

Example: Anonymous class serialization

use Serializor\Serializor;

$obj = new class("Hello from anonymous class!") {
    public function __construct(private string $message) {}

    public function greet(): string {
        return $this->message;
    }
};

$serialized = Serializor::serialize($obj);
$restored = Serializor::unserialize($serialized);

echo $restored->greet(); // Hello from anonymous class!

Example: Readonly properties (no class modifications)

use Serializor\Serializor;

class MyService {
    public readonly Closure $handler;

    public function __construct() {
        $this->handler = fn($x) => $x * 2;
    }
}

$service = new MyService();
$serialized = Serializor::serialize($service);  // Just works
$restored = Serializor::unserialize($serialized);

echo ($restored->handler)(21); // 42

Installation

Serializor is available on Packagist and can be installed via Composer:

composer require frodeborli/serializor

Requirements

  • PHP >= 8.2

Security

By default, Serializor does not sign serialized data. For production use, especially in distributed systems or job queues, you should set a shared secret:

use Serializor\Serializor;

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

When a secret is set, all serialized data is HMAC-signed to prevent tampering.

Custom Serializers

For types that need special handling (like database connections that must be reconnected), you can register custom serialization logic:

use Serializor\Stasis;

Stasis::registerFactory(PDO::class, function (PDO $pdo): MyPDOStasis {
    return MyPDOStasis::fromPDO($pdo);
});

See tests/Transformers/CustomTransformerTest.php for a complete example.

Comparison with Other Libraries

Feature Serializor opis/closure 4.x laravel/serializable-closure
Closure serialization Yes Yes Yes
Anonymous class serialization Yes Yes No
No wrapper classes required Yes Yes No
Readonly Closure properties Yes Requires __serialize() No
WeakReference / WeakMap Yes Yes No
SplObjectStorage Yes Yes No
HMAC signing Yes Yes Yes
Test coverage 277 tests ~70 tests ~130 tests

Serializor's advantages:

  • Works with typed readonly properties and third-party objects without any class modifications
  • Most comprehensive test suite covering edge cases from opis/closure GitHub issues
  • Supports PHP 8.2-8.5 features including property hooks and pipe operator

Migrating from Laravel or Opis

Serializor can unserialize data that was serialized by laravel/serializable-closure or opis/closure, providing a seamless upgrade path. The original library must remain installed for deserialization to work:

use Serializor\Serializor;

// Data serialized with Laravel or Opis can be unserialized with Serializor
// (requires the original library to be installed)
$closure = Serializor::unserialize($legacySerializedData);

// Re-serialize with Serializor - no longer requires the old library
$newSerializedData = Serializor::serialize($closure);

This allows gradual migration: keep the old library installed while transitioning, then remove it once all stored data has been re-serialized with Serializor.

Known Limitations

  • Anonymous classes extending internal PHP classes (stdClass, ArrayObject) cannot be serialized
  • Multiple closures on the same line with identical signatures cannot be distinguished (PHP limitation)

History

Serializor was first released on September 5, 2024, introducing a novel architecture for PHP closure serialization: direct serialization without wrapper classes, stream wrapper-based reconstruction, WeakMap + ReflectionReference cycle detection, and an extensible transformer system.

Four months later, Opis/Closure v4.0.0 (December 2024) was released as a "complete rewrite" featuring remarkably similar architectural choices. For a detailed technical comparison, see DESIGN.md.

Performance

Serialization

Unserialization

License

Serializor is licensed under the MIT License.