Skip to content

Tips on message serialization

Walter Dal Mut edited this page Jan 23, 2017 · 5 revisions

As you know the queue project accepts only strings or string serializable objects.

Serializable objects example (__toString)

class JsonMessage
{
    private $payload;

    public function __construct($payload)
    {
        $this->payload = $payload;
    }

    public function __toString()
    {
        return json_encode($this->payload);
    }

    public static function decode($payload)
    {
        return [$payload[0], json_decode($payload[1], true)];
    }
}

$queue->send(new JsonMessage(["test" => "ok", "test2" => true])); // the message will be sent as {"test":"ok","test2":true}
list($receipt, $message) = JsonMessage::decode($queue->receive()); // message is decode as php array

Use models and serializers

If you have a serializer like symfony/serializer you can use a proxy for the queue and pass your entities to the proxy

class QueueProxy extends Queue
{
    public function send($message, array $options = [])
    {
        $message = $this->serializer->serialize($message, json, ["groups" => $options["groups"]]);
        return parent::send($message, $options);
    }
}

// your model
$item = new Item();
$item->setCode(...); // prepare your thing
$createItemCommand = new CreateItemCommand($item); // create a command

// The serializer will create the json representation
$queueProxy->send($createItemCommand, ["groups" => "item", "timestamps"]); 

Thanks to serializers/deserializer you can also deserialize messages

class QueueProxy extends Queue
{
    public function __construct($queueName, $adapter, $prototype, $serializer)
    {
         $this->prototype = $prototype;
         $this->serializer = $serializer;
         parent::__construct($queuName, $adapter);
    }

    public function receive(array $options = [])
    {
        list($receipt, $message) = $this->receive($options);

        $message = $this->serializer->deserialize($message, $this->prototype, "json");
        return [$receipt, $message];
    }
}

If you have also a dependency injection container (like symfony/dependency-injection)

services:
  app.queue:
    class: AppBundle\Service\Queue\QueueProxy
    arguments:
      - "%queue_create_items%"
      - "@app.queue.adapter
      - "AppBundle\Event\CreateCommandItem"
      - "@serializer"
   
  app.createItemCommand:
    class: AppBundle\Model\CreateItemCommand