本文介绍PB协议与PHP语言相关的特性和知识点,以及如何使用PHP解析pb协议。
· packages
proto文件指定了package后,在编译为PHP文件时会根据package包名路径为构建出的PHP文件设置命名空间,并且创建对应命名空间的目录。
protoc编译器会为上述proto文件生成的PHP文件设置命名空间为 "Foo\Bar\MyMessage"。
· Messages
如上所示,PB编译器生成PHP代码后,PHP代码里会包含一个Foo的类。Foo类继承了PB提供的Message基类,Message基类提供了一系列的访问器和修改器供我们访问和修改message中的字段。
又例如:
Message对象还提供了序列化和反序列化的方法。
serializeToString:序列化成二进制字符串
serializeToJsonString:序列化成JSON字符串
mergeFromString:二进制字符串反序列化
mergeFromJsonString:Json字符串反序列化
序列化示例
反序列化示例
获取一个已有内容的message的所有字段值
注意:
1、当你使用修改器(set方法)修改message的一个字段时,PHP 会根据该字段的声明类型对该值进行类型检查。如果值的类型错误(或超出范围),则会引发异常。默认情况下,允许在整数、浮点数和数字字符串之间进行类型转换。不允许的转换包括与数组或对象的所有转换。
2、消息类型的字段(即字段的类型是一个嵌套message)的默认值是null,且访问该字段时不会自动创建。因此,您需要显式创建子消息。
例如:
3、repeated字段和map字段的操作类似数组
proto文件内容:
生成的PHP代码允许您执行此操作:
需要注意,PHP中使用message对象的访问器获取一个repeated对象时,返回的是一个RepeatedField对象,而非数组。如果需要得到数组,可以使用iterator_to_array()函数。
4、PHP没有原生枚举,因此PB编译器会为.proto文件中的每个枚举类型生成一个 PHP 类。
编译后:
5、对于oneof,PB 编译器生成与常规单数字段相同的代码,但还添加了一个特殊的访问器方法,可让您找出设置了哪个 oneof 字段(如果有)。此时如果要用访问器或修改器方法,就不再是get某个具体字段。
编译器编译成的PHP文件会生成以下字段和特殊方法:
访问器方法的名称基于 oneof 的名称,并返回一个枚举值,该值表示当前设置的 oneof 中的字段值。
6、对any类型的字段设置值时,不能够直接设置而是要使用setValue()方法。
正确做法:
需要注意,any类型是一种泛型,因此设置的时候必须指定any实际的类型,否则在反编码的时候程序就不知道应该按整型、字符串还是map或数组等类型对其进行反编码。因此 protobuf 提供了type url属性供用户指明一个any类型的值应该按protobuf规定的哪种类型进行编码和反编码。
type url的格式一般为 type.googleapis.com/包名.message名,例如type.googleapis.com/google.protobuf.StringValue 就表示要按照protobuf官方内置的 StringValue这种内置的message类型对any类型进行解析,也就是解析为字符串格式。
protobuf内置的message类型可以在 google/protobuf 目录中查看,该目录是PHP使用composer安装 google/protobuf 依赖时生成的。