在消息队列中使用Symfony的序列化

PHP中,如果需要把内存中的变量进行保存,以便后续继续使用,那么就要把数据序列化。

PHP提供了 serialize()  和 unserialize()  这两个原生方法来完成。但是这样有个限制,就是要求写入和读取的时候使用同样的方法。就是说只能使用PHP原生的反序列化函数来读取PHP原生序列化的数据。 有时候我们写入是PHP,读取的时候可能是别语言,所以需要一种更加通用的格式。

比如,在项目的写入队列的过程中,我们打算用Symfony提供的序列化器代替PHP原生的。我们选择序列化的格式为JSON。但是出现了问题,发现某些属性的数据丢失了。原来需要对序列化的对象进行处理。

要让消息能被JSON序列化需要确认以下

  • 消息对象需要实现一下特定接口 (非必要)
  • 消息对象能被正确encode和decode
  • 消息对象的构造函数必须为public,且只使用标量值。如果必须要使用类,需要确保这些类实现了stringable接口。

消息需要实现特定接口

SyncCommandInterface::class,
AsyncCommandInterface::class,
EventInterface::class,
QueryInterface::class,

具体措施

消息的构造函数必须为public,且使用仅使用标量作为参数

为什么消息对象的构造函数必须为public,为啥必须用标量参数。

我猜想,因为当消息被反序列化的时候,系统只会用最简单的new方法来重新创建消息实例。

  • public类的属性

使用readonly修饰属性防止意外修改

使用标量值

对象必须实现stringable

减少复杂性。比如不使用实体对象entity,而使用id. 这点在Symfony的文档内也有介绍。

参考