- Enhance logging handlers (Console, DockerJson, File, JsonFile, MultiFile) - Improve exception and line formatters - Update logger initialization and processor management - Add Ansible playbooks for staging 502 error troubleshooting - Update deployment documentation - Fix serializer and queue components - Update error kernel and queued log handler
Serializer Module
The Serializer module provides a unified way to serialize and deserialize data in various formats. It supports JSON and PHP serialization with plans to add more formats in the future.
Features
- Unified interface for all serializers
- Type-safe serialization and deserialization
- Robust error handling
- Configurable serialization options
- Factory methods for common configurations
Usage
Basic Usage
use App\Framework\Serializer\SerializerFactory;
// Create a JSON serializer with default settings (pretty print)
$serializer = SerializerFactory::createJsonSerializer();
// Serialize data
$data = ['name' => 'John', 'age' => 30];
$json = $serializer->serialize($data);
// Deserialize data
$deserializedData = $serializer->deserialize($json);
Serialization Options
The module provides several factory methods for common serialization configurations:
// Pretty-printed JSON (default)
$prettySerializer = SerializerFactory::createPrettyJsonSerializer();
$prettyJson = $prettySerializer->serialize($data);
// Result: {
// "name": "John",
// "age": 30
// }
// Compact JSON (no whitespace)
$compactSerializer = SerializerFactory::createCompactJsonSerializer();
$compactJson = $compactSerializer->serialize($data);
// Result: {"name":"John","age":30}
// Minimal JSON (no special flags)
$minimalSerializer = SerializerFactory::createMinimalJsonSerializer();
$minimalJson = $minimalSerializer->serialize($data);
// Result: {"name":"John","age":30}
Custom Configuration
You can create a serializer with custom configuration:
// Custom JSON serializer with specific flags
$customSerializer = SerializerFactory::createCustomJsonSerializer(
JSON_FORCE_OBJECT | JSON_UNESCAPED_UNICODE,
256 // Max depth
);
// Serialize an array as an object
$data = ['a', 'b', 'c'];
$json = $customSerializer->serialize($data);
// Result: {"0":"a","1":"b","2":"c"}
Using Config Objects Directly
You can also create and use config objects directly:
use App\Framework\Serializer\Json\JsonSerializer;
use App\Framework\Serializer\Json\JsonSerializerConfig;
// Create a config object
$config = new JsonSerializerConfig(
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
512
);
// Create a serializer with the config
$serializer = new JsonSerializer($config);
// Or use the factory methods on the config class
$compactConfig = JsonSerializerConfig::compact();
$prettyConfig = JsonSerializerConfig::pretty();
$minimalConfig = JsonSerializerConfig::minimal();
// Create serializers with these configs
$compactSerializer = new JsonSerializer($compactConfig);
$prettySerializer = new JsonSerializer($prettyConfig);
$minimalSerializer = new JsonSerializer($minimalConfig);
Exception Handling
The serializer module provides a dedicated exception hierarchy for better error handling:
SerializerException: Base exception for all serializer-related exceptionsSerializeException: Thrown when serialization failsDeserializeException: Thrown when deserialization fails
Example of handling deserialization errors:
use App\Framework\Serializer\SerializerFactory;
use App\Framework\Serializer\Exception\SerializeException;
use App\Framework\Serializer\Exception\DeserializeException;
$serializer = SerializerFactory::createJsonSerializer();
try {
// Try to deserialize invalid JSON
$data = $serializer->deserialize('{"name": "John", }'); // Invalid JSON
} catch (DeserializeException $e) {
// Handle deserialization errors
echo "Deserialization error: " . $e->getMessage();
} catch (SerializeException $e) {
// Handle serialization errors
echo "Serialization error: " . $e->getMessage();
} catch (SerializerException $e) {
// Handle other serializer-related errors
echo "Serializer error: " . $e->getMessage();
}
MIME Type and File Extension
The serializer provides methods to get the MIME type and file extension:
$serializer = SerializerFactory::createJsonSerializer();
// Get MIME type
$mimeType = $serializer->getMimeType(); // "application/json"
// Get file extension
$extension = $serializer->getFileExtension(); // "json"
Migration from Legacy Serializers
If you're using the legacy serializers, here's how to migrate:
From Cache JsonSerializer
// Old code
use App\Framework\Cache\Serializer\JsonSerializer;
$serializer = new JsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->unserialize($json);
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createJsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->deserialize($json);
From Filesystem JsonSerializer
// Old code
use App\Framework\Filesystem\Serializers\JsonSerializer;
$serializer = new JsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->deserialize($json);
// Factory methods
$compactSerializer = JsonSerializer::compact();
$prettySerializer = JsonSerializer::pretty();
$minimalSerializer = JsonSerializer::minimal();
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createJsonSerializer();
$json = $serializer->serialize($data);
$data = $serializer->deserialize($json);
// Factory methods
$compactSerializer = SerializerFactory::createCompactJsonSerializer();
$prettySerializer = SerializerFactory::createPrettyJsonSerializer();
$minimalSerializer = SerializerFactory::createMinimalJsonSerializer();
Direct Usage of JsonSerializer
If you need direct access to the JsonSerializer class:
use App\Framework\Serializer\Json\JsonSerializer;
// Create with default settings
$serializer = new JsonSerializer();
// Create with custom settings
$serializer = new JsonSerializer(
JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES,
512
);
// Use factory methods
$compactSerializer = JsonSerializer::compact();
$prettySerializer = JsonSerializer::pretty();
$minimalSerializer = JsonSerializer::minimal();
PHP Serialization
The module also provides PHP serialization capabilities with a focus on security.
Basic Usage
use App\Framework\Serializer\SerializerFactory;
// Create a PHP serializer with default settings (safe with no allowed classes)
$serializer = SerializerFactory::createPhpSerializer();
// Serialize data
$data = ['name' => 'John', 'age' => 30];
$serialized = $serializer->serialize($data);
// Deserialize data
$deserializedData = $serializer->deserialize($serialized);
Security Considerations
PHP serialization can be a security risk if used improperly, as it allows arbitrary code execution through object deserialization. The PHP serializer in this module is designed with security in mind:
- By default, no classes are allowed to be unserialized (only primitive types and arrays)
- You can explicitly specify which classes are allowed to be unserialized
- You can create an unsafe serializer if you need to deserialize any class (use with caution)
Safe and Unsafe Deserialization
use App\Framework\Serializer\SerializerFactory;
// Safe serializer with specific allowed classes
$safeSerializer = SerializerFactory::createSafePhpSerializer(['stdClass', 'DateTime']);
// Unsafe serializer (allows all classes - use with caution)
$unsafeSerializer = SerializerFactory::createUnsafePhpSerializer();
Custom Configuration
You can create a serializer with custom options:
use App\Framework\Serializer\SerializerFactory;
// Custom PHP serializer with specific allowed classes and max depth
$customSerializer = SerializerFactory::createCustomPhpSerializer(
['MyClass', 'MyOtherClass'], // allowed classes
4096 // max depth (optional, defaults to 4096)
);
Using PhpSerializer with Config Objects
You can create and use PHP serializer config objects directly:
use App\Framework\Serializer\Php\PhpSerializer;
use App\Framework\Serializer\Php\PhpSerializerConfig;
// Create with default settings (safe with no allowed classes)
$serializer = new PhpSerializer();
// Create a config object with custom options
$config = new PhpSerializerConfig(
['MyClass'], // allowed classes
4096 // max depth (optional, defaults to 4096)
);
// Create a serializer with the config
$serializer = new PhpSerializer($config);
// Or use the factory methods on the config class
$safeConfig = PhpSerializerConfig::safe(
['stdClass'], // allowed classes
4096 // max depth (optional, defaults to 4096)
);
$unsafeConfig = PhpSerializerConfig::unsafe(
4096 // max depth (optional, defaults to 4096)
);
// Create serializers with these configs
$safeSerializer = new PhpSerializer($safeConfig);
$unsafeSerializer = new PhpSerializer($unsafeConfig);
Migration from Legacy PHP Serializers
If you're using the legacy PHP serializers, here's how to migrate:
From Cache PhpSerializer
// Old code
use App\Framework\Cache\Serializer\PhpSerializer;
$serializer = new PhpSerializer();
$serialized = $serializer->serialize($data);
$data = $serializer->unserialize($serialized);
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createUnsafePhpSerializer(); // For backward compatibility
$serialized = $serializer->serialize($data);
$data = $serializer->deserialize($serialized);
From Filesystem PhpSerializer
// Old code
use App\Framework\Filesystem\Serializers\PhpSerializer;
$serializer = new PhpSerializer();
$serialized = $serializer->serialize($data);
$data = $serializer->deserialize($data);
// Factory methods
$safeSerializer = PhpSerializer::safe(['stdClass']);
$unsafeSerializer = PhpSerializer::unsafe();
// New code
use App\Framework\Serializer\SerializerFactory;
$serializer = SerializerFactory::createPhpSerializer();
$serialized = $serializer->serialize($data);
$data = $serializer->deserialize($serialized);
// Factory methods
$safeSerializer = SerializerFactory::createSafePhpSerializer(['stdClass']);
$unsafeSerializer = SerializerFactory::createUnsafePhpSerializer();