basho / protobuf
PHP的Protocol Buffer支持
Requires
- php: >=7.0
Requires (Dev)
- google/protobuf: v2.6.1
- phpunit/phpunit: 5.7.*
This package is not auto-updated.
Last update: 2024-09-12 19:22:23 UTC
README
Protocol Buffers(协议缓冲区)是一种高效且可扩展的格式,用于对结构化数据进行编码。它可能用于文件格式和RPC协议。
PHP Protobuf是Google为PHP实现的Protocol Buffers,目标是提供高性能,包括一个从.proto文件生成PHP类的protoc
插件。解析(解析和序列化)的工作由PHP扩展完成。
安装
依赖
- PHP 5.4或更高版本
- Protobuf
protoc
编译器2.6或更高版本 - Protobuf消息版本
proto2
Composer安装
从源代码安装
- 克隆源代码
git clone https://github.com/allegro/php-protobuf
- 进入源代码目录
cd php-protobuf
- 构建和安装PHP扩展(遵循php.net上的说明)
- 安装protoc插件依赖项
composer install
文档
-
假设你有一个文件
foo.proto
message Foo { required int32 bar = 1; optional string baz = 2; repeated float spam = 3; }
-
编译
foo.proto
php protoc-gen-php.php foo.proto
-
创建
Foo
消息并用一些数据填充它require_once 'Foo.php'; $foo = new Foo(); $foo->setBar(1); $foo->setBaz('two'); $foo->appendSpam(3.0); $foo->appendSpam(4.0);
-
将消息序列化成字符串
$packed = $foo->serializeToString();
-
从字符串解析消息
$parsedFoo = new Foo(); try { $parsedFoo->parseFromString($packed); } catch (Exception $ex) { die('Oops.. there is a bug in this example, ' . $ex->getMessage()); }
-
看看我们解析出了什么
$parsedFoo->dump();
它应该生成以下类似的输出
Foo { 1: bar => 1 2: baz => 'two' 3: spam(2) => [0] => 3 [1] => 4 }
-
如果你想,你可以将对象重置为其初始状态
$parsedFoo->reset();
编译
使用protoc-php.php脚本编译你的proto文件。它需要已安装的扩展。
php protoc-php.php foo.proto
指定--use-namespaces或-n选项,以使用原生PHP命名空间生成类。
php protoc-php.php -n foo.proto
包
如果使用-n / --use-namespaces选项编译了proto文件,则包表示为一个命名空间。否则,消息和枚举名称前面会加上它,并用下划线分隔。包名称由相应的首字母大写部分组成,并用下划线分隔。
消息和枚举名称
- 下划线分隔的名称被转换为驼峰式
- 嵌套名称由父消息名称组成,并用下划线分隔
消息接口
PHP Protobuf模块实现了ProtobufMessage类,该类封装了协议逻辑。从proto文件编译的消息扩展了这个类,提供了消息字段描述符。基于这些描述符,ProtobufMessage知道如何解析和序列化给定类型的消息。
为每个字段生成一组访问器。实际可访问的方法对于单值字段(required / optional)和多值字段(repeated)不同。
-
required / optional
get{FIELD}() // return field value set{FIELD}($value) // set field value to $value
-
repeated
append{FIELD}($value) // append $value value to field clear{FIELD}() // empty field get{FIELD}() // return array of field values getAt{FIELD}($index) // return field value at $index index getCount{FIELD}() // return number of field values getIterator{FIELD}($index) // return ArrayIterator for field values
{FIELD}是驼峰式字段名称。
枚举
PHP没有原生支持枚举类型。因此,枚举被编译成一个包含一组常量的类。
枚举字段是简单的PHP整型。
类型映射
可用的内置PHP类型范围对某些限制。PHP不支持64位正整数类型。请注意,解析大整数值可能会导致得到意外的结果。
Protocol Buffers类型映射到PHP类型如下
| Protocol Buffers | PHP |
| ---------------- | ------ |
| double | float |
| float | |
| ---------------- | ------ |
| int32 | int |
| int64 | |
| uint32 | |
| uint64 | |
| sint32 | |
| sint64 | |
| fixed32 | |
| fixed64 | |
| sfixed32 | |
| sfixed64 | |
| ---------------- | ------ |
| bool | bool |
| ---------------- | ------ |
| string | string |
| bytes | |
未设置值用null类型表示。要取消设置值,只需将其值设置为null。
解析
要解析消息,请创建消息类实例并调用其parseFromString方法,传入序列化前的消息。遇到的错误将通过抛出Exception来通知。异常信息提供了详细的解释。未设置的必填字段将被静默忽略。
$packed = /* serialized FooMessage */;
$foo = new FooMessage();
try {
$foo->parseFromString($packed);
} catch (Exception $ex) {
die('Parse error: ' . $e->getMessage());
}
$foo->dump(); // see what you got
序列化
要序列化消息,请调用serializeToString方法。它返回一个包含protobuf编码消息的字符串。遇到的错误将通过抛出Exception来通知。异常信息提供了详细的解释。未设置的必填字段将触发错误。
$foo = new FooMessage()
$foo->setBar(1);
try {
$packed = $foo->serializeToString();
} catch (Exception $ex) {
die 'Serialize error: ' . $e->getMessage();
}
/* do some cool stuff with protobuf-encoded $packed */
转储
可能存在需要调查给定消息实际内容的情况。对消息实例的var_dump输出有些模糊不清。
ProtobufMessage类提供了一个dump方法,可以将消息内容打印到标准输出。它接受一个可选参数,指定是否只想转储已设置的字段。默认情况下,它只转储已设置的字段。将false作为参数传递以转储所有字段。它产生的格式类似于var_dump。
示例
-
foo.proto
message Foo { required int32 bar = 1; optional string baz = 2; repeated float spam = 3; }
-
pb_proto_foo.php
php protoc-php.php foo.proto
-
foo.php
<?php require_once 'pb_proto_foo.php'; $foo = new Foo(); $foo->setBar(1); $foo->setBaz('two'); $foo->appendSpam(3.0); $foo->appendSpam(4.0); $packed = $foo->serializeToString(); $foo->clear(); try { $foo->parseFromString($packed); } catch (Exception $ex) { die('Oops.. there is a bug in this example'); } $foo->dump(); ?>
php foo.php
应该产生以下输出
Foo {
1: bar => 1
2: baz => 'two'
3: spam(2) =>
[0] => 3
[1] => 4
}
许可证和作者
- 作者:Hubert Jagodziński (https://github.com/hjagodzinski)
- 作者:Mateusz Gajewski (https://github.com/wendigo)
- 作者:Sergey P (https://github.com/serggp)
- 作者:Christopher Mancini (https://github.com/christophermancini)
版权所有(c)2017 Allegro Group(原作者) 版权所有(c)2017 Basho Technologies, Inc。
许可协议:Apache License,版本2.0(“许可协议”)。有关更多详细信息,请参阅许可协议。