amphp/serialization
AMPHP serialization tools for IPC and storage in PHP. Provides a Serializer interface with JSON, native PHP serialize/unserialize, and passthrough implementations, plus optional payload compression via a wrapping serializer.
Installation:
composer require amphp/serialization
Ensure your project uses PHP 7.4+ (hard requirement).
Basic Usage:
use Amp\Serialization\JsonSerializer;
use Amp\Serialization\NativeSerializer;
use Amp\Serialization\CompressingSerializer;
// For interoperable, human-readable data (e.g., logs, configs)
$jsonSerializer = new JsonSerializer();
$serialized = $jsonSerializer->serialize(['key' => 'value']);
$deserialized = $jsonSerializer->unserialize($serialized);
// For internal IPC with compression (e.g., worker pools)
$compressedSerializer = new CompressingSerializer(new NativeSerializer());
$payload = $compressedSerializer->serialize([
'task' => fn() => 'async_work',
'data' => new stdClass()
]);
First Use Case:
$socket = new Amp\Socket\Socket('unix:///tmp/worker.sock');
$serializer = new CompressingSerializer(new NativeSerializer());
socket_write($socket, $serializer->serialize(['task' => $closure]));
Amp\Serialization\Serializer for method signatures and exceptions.JsonSerializer for JSON-based workflows.NativeSerializer for PHP-native types (use cautiously).CompressingSerializer for payload optimization.SerializationException for error handling.Layered Serialization: Combine serializers for specific needs (e.g., compression + native types):
$serializer = new CompressingSerializer(
new NativeSerializer()
);
Passthrough for Already-Serialized Data:
Avoid double-serialization with PassthroughSerializer:
$passthrough = new PassthroughSerializer();
$alreadySerialized = $passthrough->serialize('existing_string');
Error Handling: Wrap serialization in try-catch blocks for async contexts:
try {
$data = $serializer->unserialize($payload);
} catch (SerializationException $e) {
// Fallback to JsonSerializer or rethrow
throw new RuntimeException('Failed to deserialize payload', 0, $e);
}
AMPHP Worker Pools:
NativeSerializer + compression.// Master process
$task = ['command' => 'process', 'args' => $data];
$serializedTask = $serializer->serialize($task);
$worker->send($serializedTask);
// Worker process
$task = $serializer->unserialize($receivedPayload);
Shared Memory:
Use NativeSerializer for complex objects (e.g., Amp\ByteStream\Buffer):
$sharedMemory = new Amp\SharedMemory\Segment();
$serializer = new NativeSerializer();
$sharedMemory->write($serializer->serialize($object));
Hybrid Serialization:
Conditionally use JsonSerializer for public data and NativeSerializer for internal IPC:
$serializer = $isInternalIpc
? new CompressingSerializer(new NativeSerializer())
: new JsonSerializer();
Laravel Compatibility:
json_encode() or spatie/array-to-object instead.Illuminate\Bus\Queueable with custom serialization:
public function serialize(): array
{
return ['data' => $this->data]; // Simplified; use NativeSerializer for complex types
}
AMPHP Integration:
amphp/byte-stream for socket-based IPC:
use Amp\ByteStream\Socket;
use Amp\Serialization\CompressingSerializer;
$socket = Socket::connect('tcp://worker:1234');
$serializer = new CompressingSerializer(new NativeSerializer());
socket_write($socket, $serializer->serialize($message));
Testing:
Serializer interface for unit tests:
$mockSerializer = $this->createMock(Serializer::class);
$mockSerializer->method('serialize')->willReturn('mocked');
$mockSerializer->method('unserialize')->willReturn(['data' => 'test']);
Performance:
$data = ['large' => str_repeat('x', 1024)];
$jsonSize = strlen((new JsonSerializer())->serialize($data));
$compressedSize = strlen((new CompressingSerializer(new NativeSerializer()))->serialize($data));
// Compare $jsonSize vs. $compressedSize
PHP 7.4+ Hard Requirement:
Class 'Amp\Serialization\Serializer' not found on PHP 8.x.composer.json or use a fork with PHP 8.x support.NativeSerializer Security Risks:
unserialize() can execute arbitrary code.$serializer = new NativeSerializer();
$serializer->setAllowedClasses(['App\Task', 'Amp\ByteStream\Buffer']);
JsonSerializer for untrusted data.Circular References:
NativeSerializer may fail on circular references.JsonSerializer or implement custom logic:
$serializer = new JsonSerializer(JsonSerializer::FLAGS_DISALLOW_CIRCULAR_REFERENCES);
Closure/Resource Serialization:
JsonSerializer cannot serialize closures/resources.NativeSerializer but restrict to trusted contexts.Compression Overhead:
CompressingSerializer.Attribute Conflicts (PHP 8.x):
#[Override] may conflict with Laravel attributes (e.g., #[Cacheable]).Serialization Failures:
JsonSerializer.NativeSerializer for complex objects but validate inputs.Corrupted Payloads:
$payload = $serializer->serialize($data);
$checksum = hash('crc32b', $payload);
Performance Bottlenecks:
CompressingSerializer:
$data = ['large' => str_repeat('x', 1024 * 1024)]; // 1MB
$start = microtime(true);
$serialized = (new CompressingSerializer(new NativeSerializer()))->serialize($data);
$time = microtime(true) - $start;
// Log $time and strlen($serialized)
NativeSerializer Allowed Classes:
unserialize() risks:
$serializer = new NativeSerializer();
$serializer->setAllowedClasses([
Amp\ByteStream\Buffer::class,
App\Task::class,
]);
JSON Flags:
JsonSerializer for strict parsing:
$serializer = new JsonSerializer(
JsonSerializer::FLAGS_DISALLOW_CIRCULAR_REFERENCES |
JsonSerializer::FLAGS_DISALLOW
How can I help you explore Laravel packages today?