jacknoordhuis / php-protobuf
Google的Protocol Buffers for PHP
Requires
- php: >=5.3
- pear/console_commandline: ^1.2
README
概述
Protocol Buffers(协议缓冲区)是一种以高效且可扩展的格式编码结构化数据的方法。它可以用于文件格式和RPC协议。
PHP Protobuf是Google为PHP实现的Protocol Buffers,旨在提供高性能,包括一个protoc
插件,用于从.proto文件生成PHP类。重负载(解析和序列化)由PHP扩展完成。
要求
- PHP 7.0或更高版本(对于PHP 5支持,请参阅php5分支)
- Pear的Console_CommandLine(用于protoc插件)
- Google的protoc编译器版本2.6或更高
入门指南
安装
-
克隆源代码
git clone https://github.com/allegro/php-protobuf
-
进入源代码目录
cd php-protobuf
-
构建并安装PHP扩展(遵循php.net上的说明)
-
安装protoc插件依赖项
composer install
全局Composer安装
-
定位您的全局Composer目录(通常是~/.composer)
-
将Git仓库添加到composer.json
"repositories": [ { "type": "vcs", "url": "https://github.com/JackNoordhuis/php-protobuf" } ]
-
将库作为全局依赖项添加
"require": [ "jacknoordhuis/php-protobuf": "dev-master" ]
-
最后,运行
composer global update
以安装所需依赖项 -
现在您可以从任何位置运行
protoc-gen-php
命令
用法
-
假设您有一个名为
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();
指南
编译
PHP Protobuf附带Google的protoc编译器插件。您可以直接运行
php protoc-gen-php.php -o output_dir foo.proto
或将其传递给protoc
protoc --plugin=protoc-gen-allegrophp=protoc-gen-php.php --allegrophp_out=output_dir foo.proto
在Windows上使用protoc-gen-php.bat
代替。
命令行选项
- -o out, --out=out - 生成文件的目标目录(默认为当前目录)。
- -I proto_path, --proto_path=proto_path - 搜索导入的目录。
- --protoc=protoc - protoc编译器可执行文件的路径。
- -D define, --define=define - 定义生成器选项(例如 -Dnamespace='Foo\Bar\Baz')。
生成器选项
- namespace - 要由生成的PHP类使用的命名空间。
消息类
编译期间生成的类符合PSR-0规范(每个类都放入它自己的文件)。如果没有定义namespace
生成器选项,则使用包名(如果存在)来创建命名空间。如果没有设置包名,则将类放入全局空间。
PHP Protobuf模块实现了ProtobufMessage
类,该类封装了协议逻辑。从proto文件编译的消息扩展了这个类,提供了消息字段描述符。基于这些描述符,ProtobufMessage知道如何解析和序列化给定类型的消息。
为每个字段生成一组访问器。方法集对于单值字段(required
/ optional
)和多值字段(repeated
)不同。
-
required
/optional
get{FIELD}() // return a field value has{FIELD}() // check whether a field is set set{FIELD}($value) // set a field value to $value
-
repeated
append{FIELD}($value) // append $value to a field clear{FIELD}() // empty field get{FIELD}() // return an array of field values getAt{FIELD}($index) // return a field value at $index index getCount{FIELD}() // return a number of field values has{FIELD}() // check whether a field is set getIterator{FIELD}() // return an ArrayIterator
{FIELD}是驼峰式的字段名。
枚举
PHP 原生不支持枚举类型。因此,枚举类型由 PHP 整数类型表示。为了方便,枚举会被编译成一个类,其中包含对应其可能值的常量集合。
类型映射
可用的内置 PHP 类型范围存在一些限制。PHP 不支持 64 位正整数类型。请注意,解析大整数值可能会导致出现意外结果。
Protocol Buffers 类型映射到 PHP 类型如下(x86_64)
| Protocol Buffers | PHP |
| ---------------- | ------ |
| double | float |
| float | |
| ---------------- | ------ |
| int32 | int |
| int64 | |
| uint32 | |
| uint64 | |
| sint32 | |
| sint64 | |
| fixed32 | |
| fixed64 | |
| sfixed32 | |
| sfixed64 | |
| ---------------- | ------ |
| bool | bool |
| ---------------- | ------ |
| string | string |
| bytes | |
Protocol Buffers 类型映射到 PHP 类型如下(x86)
| Protocol Buffers | PHP |
| ---------------- | --------------------------- |
| double | float |
| float | |
| ---------------- | --------------------------- |
| int32 | int |
| uint32 | |
| sint32 | |
| fixed32 | |
| sfixed32 | |
| ---------------- | --------------------------- |
| int64 | if val <= PHP_INT_MAX |
| uint64 | then value is stored as int |
| sint64 | otherwise as double |
| fixed64 | |
| 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
。
或者,您可以使用 printDebugString()
方法,该方法以协议缓冲区文本格式生成输出。
IDE 辅助工具和自动完成支持
要将此扩展与您的 IDE(PhpStorm、Eclipse 等)集成并获得自动完成支持,只需在项目根目录下任何位置包含 stubs\ProtobufMessage.php
即可。
已知问题
参考文献
致谢
- PHP7 支持(Sergey)