PB协议(二)Protobuf的PHP开发教程
本文介绍PB协议与PHP语言相关的特性和知识点,以及如何使用PHP解析pb协议。
· packages
proto文件指定了package后,在编译为PHP文件时会根据package包名路径为构建出的PHP文件设置命名空间,并且创建对应命名空间的目录。
package foo.bar;message MyMessage {}
protoc编译器会为上述proto文件生成的PHP文件设置命名空间为 “Foo\Bar\MyMessage”。
· Messages
message Person { string name = 1; int32 age = 2; string sex = 3;}
如上所示,PB编译器生成PHP代码后,PHP代码里会包含一个Foo的类。Foo类继承了PB提供的Message基类,Message基类提供了一系列的访问器和修改器供我们访问和修改message中的字段。
$person = new Test\Person();$person->setName("lailaiji");$person->setAge("28");$person->setSex(true);$data = $person->serializeToString();file_put_contents('data.bin',$data);
又例如:
$m = new MyMessage();$m->setX(1);$val = $m->getX();$a = 1;$m->setX($a);
Message对象还提供了序列化和反序列化的方法。
serializeToString:序列化成二进制字符串
serializeToJsonString:序列化成JSON字符串
mergeFromString:二进制字符串反序列化
mergeFromJsonString:Json字符串反序列化
序列化示例
setName("lailaiji");$person->setAge("28");$person->setSex(true);$data = $person->serializeToString();file_put_contents('data.bin',$data);
反序列化示例
mergeFromString($bindata);echo $person->getName();
获取一个已有内容的message的所有字段值
$json = $message->serializeToJsonString();$data = json_decode($json, true);
注意:
当你使用修改器(set方法)修改message的一个字段时,PHP 会根据该字段的声明类型对该值进行类型检查。如果值的类型错误(或超出范围),则会引发异常。默认情况下,允许在整数、浮点数和数字字符串之间进行类型转换。不允许的转换包括与数组或对象的所有转换。
消息类型的字段(即字段的类型是一个嵌套message)的默认值是null,且访问该字段时不会自动创建。因此,您需要显式创建子消息。
例如:
$m = new MyMessage();$m->setZ(new SubMessage());$m->getZ()->setFoo(42);$m2 = new MyMessage();$m2->getZ()->setFoo(42); // 报错,原因是getZ()返回null
repeated字段和map字段的操作类似数组
proto文件内容:
repeated int32 foo = 1;map weight = 1;
生成的PHP代码允许您执行此操作:
$m->getFoo()[] =1;$m->setFoo($array);$m->getWeight()[1] = 1;
需要注意,PHP中使用message对象的访问器获取一个repeated对象时,返回的是一个RepeatedField对象,而非数组。如果需要得到数组,可以使用iterator_to_array()函数。
$foo = iterator_to_array($m->getFoo();
PHP没有原生枚举,因此PB编译器会为.proto文件中的每个枚举类型生成一个 PHP 类。
enum TestEnum { Default = 0; A = 1;}
编译后:
class TestEnum { const DEFAULT = 0; const A = 1;}
对于oneof,PB 编译器生成与常规单数字段相同的代码,但还添加了一个特殊的访问器方法,可让您找出设置了哪个 oneof 字段(如果有)。此时如果要用访问器或修改器方法,就不再是get某个具体字段。
message TestMessage { oneof test_oneof { int32 oneof_int32 = 1; int64 oneof_int64 = 2; }}
编译器编译成的PHP文件会生成以下字段和特殊方法:
class TestMessage { private oneof_int32; private oneof_int64; public function getOneofInt32(); public function setOneofInt32($var); public function getOneofInt64(); public function setOneofInt64($var); public function getTestOneof(); // 返回字段名}
访问器方法的名称基于 oneof 的名称,并返回一个枚举值,该值表示当前设置的 oneof 中的字段值。
对any类型的字段设置值时,不能够直接设置而是要使用setValue()方法。
message TestProductAttr{ map attr = 1;}
正确做法:
$attrs = ["color"=>"read", "size"=>16];$attrPb = new \protobuf\Test\TestProductAttr();foreach($attr as $k=>$v){ $any = new \Google\Protobuf\Any(); $any->setTypeUrl('type.googleapis.com/google.protobuf.StringValue'); $any->setValue($v); $attr[$k] = $any;}$attrPb->setAttr($attrs);
需要注意,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 依赖时生成的。
更多内容请关注微信公众号:程序员阿沛 本文转载自:
张柏沛IT技术博客 > PB协议(二)Protobuf的PHP开发教程
来源地址:https://blog.csdn.net/jqsfjqsf/article/details/127473567
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341