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的文档内也有介绍。
参考
- Symfony 6.4 > Message Component > Transport Configuration > Serializing Message