Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Jms Serializer Bridge Laravel Package

simple-bus/jms-serializer-bridge

Bridge for SimpleBus Serialization that implements the ObjectSerializer interface using JMSSerializer. Use it to serialize and deserialize message objects in SimpleBus-based applications with a familiar JMS Serializer backend.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Install Dependencies:

    composer require simple-bus/jms-serializer-bridge jms/serializer
    
    • Note: jms/serializer is a required peer dependency.
  2. Configure JMSSerializer: Add a configuration file (e.g., config/jms_serializer.php) or use Symfony’s YAML setup:

    # config/packages/jms_serializer.yaml (Symfony-style)
    jms_serializer:
        metadata:
            directories:
                - %kernel.project_dir%/config/serializer
    
    • Create a serializer directory in your project root and define metadata for your message classes (e.g., MyMessage.yaml):
      App\Messages\MyMessage:
          exclusion_policy: ALL
          properties:
              id:
                  expose: true
                  type: integer
              name:
                  expose: true
                  type: string
      
  3. Bind the Serializer: Register the bridge in a Laravel service provider:

    use SimpleBus\Serialization\Serializer;
    use SimpleBus\JMSSerializerBridge\JMSSerializer;
    
    public function register()
    {
        $this->app->singleton(Serializer::class, function ($app) {
            return new JMSSerializer();
        });
    }
    
  4. First Use Case: Serialize a message in a job or command:

    use SimpleBus\Serialization\Serializer;
    
    class SendMessageJob implements ShouldQueue
    {
        public function __construct(
            private MyMessage $message,
            private Serializer $serializer
        ) {}
    
        public function handle()
        {
            $serialized = $this->serializer->serialize($this->message);
            // Store or send $serialized (e.g., to a queue)
        }
    }
    

Implementation Patterns

Core Workflows

  1. Message-Driven Architecture:

    • Producer Side:
      $serializer->serialize($message); // Convert to string for queue/storage
      
    • Consumer Side:
      $deserialized = $serializer->deserialize($serializedString, MyMessage::class);
      
    • Example: Use with Laravel Queues:
      Queue::push(function () use ($serializer, $message) {
          $serialized = $serializer->serialize($message);
          // Store $serialized in DB/Redis
      });
      
  2. Event Serialization:

    • Replace Laravel’s native event serialization:
      // Before: json_encode($event)
      // After:
      $serializer->serialize($event);
      
  3. DTO Handling:

    • Serialize complex DTOs with nested objects:
      class UserProfileDto {
          public function __construct(
              public User $user,
              public array $permissions
          ) {}
      }
      
      • Define metadata for User and permissions in YAML.
  4. Integration with SimpleBus:

    • Use the bridge as the default serializer in SimpleBus:
      $bus = new SimpleBus\Message\Bus\MessageBus(
          new SimpleBus\Message\Bus\Plugin\Router(),
          new SimpleBus\Message\Bus\Plugin\HandlerResolution\HandlerResolutionPlugin(),
          new SimpleBus\Message\Bus\Plugin\LoggingPlugin(),
          new SimpleBus\Message\Bus\Plugin\SerializationPlugin($serializer)
      );
      

Laravel-Specific Patterns

  1. Queue Job Serialization:

    • Override Laravel’s default job serialization:
      class CustomJobSerializer implements ShouldQueue
      {
          public function __construct(private Serializer $serializer) {}
      
          public function handle()
          {
              $this->serializer->serialize($this);
          }
      
          public function serialize(): string
          {
              return $this->serializer->serialize($this);
          }
      
          public static function deserialize($data): self
          {
              return $this->serializer->deserialize($data, static::class);
          }
      }
      
  2. Middleware for API ↔ Message Bridge:

    • Convert HTTP requests/responses to/from messages:
      $serializer->serialize($request->all()); // For outgoing messages
      $deserialized = $serializer->deserialize($messageString, MyRequestDto::class);
      
  3. Testing:

    • Mock the serializer in unit tests:
      $serializer = $this->createMock(Serializer::class);
      $serializer->method('serialize')->willReturn('serialized_string');
      $serializer->method('deserialize')->willReturn(new MyMessage());
      

Performance Optimization

  1. Metadata Caching:

    • Enable JMSSerializer’s metadata cache:
      $serializer = new JMSSerializer([
          'metadata' => [
              'cache_dir' => storage_path('framework/cache/jms_serializer'),
          ],
      ]);
      
  2. Batch Processing:

    • Reuse serializer instances for bulk operations:
      $serializer = app(Serializer::class);
      foreach ($messages as $message) {
          $serializer->serialize($message);
      }
      
  3. Lazy Loading:

    • Defer serialization until needed (e.g., in queue jobs):
      public function handle()
      {
          $this->delay(fn() => $this->serializer->serialize($this));
      }
      

Gotchas and Tips

Common Pitfalls

  1. Unserializable Types:

    • Issue: Custom classes (e.g., Eloquent models, Carbon instances) fail without metadata.
    • Fix: Define types in YAML or use @Serializer\Type annotations:
      App\Models\User:
          properties:
              created_at:
                  type: DateTime<'Y-m-d H:i:s'>
      
    • Laravel Workaround: Create a base DTO class for Laravel-specific types:
      class LaravelDto {
          public Carbon $createdAt;
          public Collection $relations;
      }
      
  2. Circular References:

    • Issue: Objects with circular references (e.g., User->posts->author->user) cause infinite loops.
    • Fix: Configure max depth in metadata:
      App\Models\User:
          max_depth: 2
      
  3. Property Visibility:

    • Issue: Private/protected properties are ignored by default.
    • Fix: Explicitly expose them in metadata:
      properties:
          secretKey:
              expose: true
              type: string
              serialized_name: secret_key
      
  4. Namespace Conflicts:

    • Issue: JMSSerializer may misinterpret Laravel’s Illuminate\Support\* classes.
    • Fix: Use fully qualified names in metadata:
      Illuminate\Support\Collection:
          properties:
              items:
                  type: array
      
  5. Queue Driver Incompatibilities:

    • Issue: Some queue drivers (e.g., database) may truncate serialized strings.
    • Fix: Use base64_encode($serialized) before storage and decode on retrieval.

Debugging Tips

  1. Enable Verbose Logging:

    • Configure JMSSerializer to log serialization errors:
      $serializer = new JMSSerializer([
          'handlers' => [
              'date_time_handler' => [
                  'format' => 'Y-m-d H:i:s',
              ],
          ],
          'debug' => true,
      ]);
      
  2. Validate Metadata:

    • Use the jms/serializer-bundle CLI tool (Symfony) or create a custom Artisan command:
      php artisan jms:validate-metadata
      
  3. Inspect Serialized Output:

    • Log serialized strings to verify structure:
      \Log::debug('Serialized:', ['data' => $serializer->serialize($message)]);
      
  4. Deserialization Errors:

    • Symptom: "Unknown type 'App\Models\User'" during deserialization.
    • Debug: Ensure the class exists and metadata is correctly configured.

Configuration Quirks

  1. YAML vs. PHP Configuration:

    • Prefer YAML for complex metadata but use PHP arrays for dynamic configurations:
      $serializer = new JMSSerializer([
          'metadata' => [
              'directories' => [__DIR__.'/config/serializer'],
          ],
          'handlers' => [
              'App\Handlers\CustomHandler',
          ],
      ]);
      
  2. Laravel Cache Integration:

    • Cache metadata in Laravel’s cache system:
      $cache = Cache::store('file');
      $serializer = new JMSSerializer([
          'metadata' => [
              'cache' => $cache,
          ],
      ]);
      
  3. Environment-Specific Config:

    • Use Laravel’s config system to switch between dev/prod settings:
      $config = config('jms_serializer', []);
      $serializer = new JMSSerializer($config);
      

Extension Points

  1. Custom Handlers:
    • Add handlers for unsupported types (e.g., Laravel collections):
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
terminal42/code-quality-tools
codifyo/ts-generator-bundle
andydefer/laravel-cluster
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity
christhompsontldr/laravel-inky