basho/protobuf

PHP的Protocol Buffer支持

v2.0.0-alpha 2017-02-02 02:47 UTC

This package is not auto-updated.

Last update: 2024-09-12 19:22:23 UTC


README

Packagist Build Status

Protocol Buffers(协议缓冲区)是一种高效且可扩展的格式,用于对结构化数据进行编码。它可能用于文件格式和RPC协议。

PHP Protobuf是Google为PHP实现的Protocol Buffers,目标是提供高性能,包括一个从.proto文件生成PHP类的protoc插件。解析(解析和序列化)的工作由PHP扩展完成。

  1. 安装
  2. 文档
  3. 贡献
  4. 路线图
  5. 许可证和作者
  6. 参考

安装

依赖

  • PHP 5.4或更高版本
  • Protobuf protoc编译器2.6或更高版本
  • Protobuf消息版本proto2

Composer安装

从源代码安装

  1. 克隆源代码
    git clone https://github.com/allegro/php-protobuf
    
  2. 进入源代码目录
    cd php-protobuf
    
  3. 构建和安装PHP扩展(遵循php.net上的说明)
  4. 安装protoc插件依赖项
    composer install
    

文档

  1. 假设你有一个文件foo.proto

    message Foo
    {
        required int32 bar = 1;
        optional string baz = 2;
        repeated float spam = 3;
    }
    
  2. 编译foo.proto

    php protoc-gen-php.php foo.proto
    
  3. 创建Foo消息并用一些数据填充它

    require_once 'Foo.php';
    
    $foo = new Foo();
    $foo->setBar(1);
    $foo->setBaz('two');
    $foo->appendSpam(3.0);
    $foo->appendSpam(4.0);
  4. 将消息序列化成字符串

    $packed = $foo->serializeToString();
  5. 从字符串解析消息

    $parsedFoo = new Foo();
    try {
        $parsedFoo->parseFromString($packed);
    } catch (Exception $ex) {
        die('Oops.. there is a bug in this example, ' . $ex->getMessage());
    }
  6. 看看我们解析出了什么

    $parsedFoo->dump();

    它应该生成以下类似的输出

    Foo {
      1: bar => 1
      2: baz => 'two'
      3: spam(2) =>
        [0] => 3
        [1] => 4
    }
    
  7. 如果你想,你可以将对象重置为其初始状态

    $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
}

许可证和作者

版权所有(c)2017 Allegro Group(原作者) 版权所有(c)2017 Basho Technologies, Inc。

许可协议:Apache License,版本2.0(“许可协议”)。有关更多详细信息,请参阅许可协议

参考