Google's Protobuf之PHP示例用法说明

搜了一遍,好像对PHP使用Protobuf的博文好少好少,因为公司有项目用到,所以这边也进行了解了一下。

google官方没有php版的使用说明,示例以allegro的php-protobuf进行说明,参考地址见本文最后面。

1. 安装php的protobuf扩展(linux)

从 https://github.com/allegro/php-protobuf 下载源代码

1) 进入源代码

2) /{php的bin目录}/phpize

3) ./configure

4) make && make install

5) 在php.ini里加入 extension=protobuf.so

6) 重启php

7) 用php -m 或 phpinfo() 查看扩展有没有安装成功

 

2. php的protobuf扩展说明

1) 继承ProtobufMessage类

2) 值的类型说明

const PB_TYPE_DOUBLE     = 1;
const PB_TYPE_FIXED_32   = 2;
const PB_TYPE_FIXED_64   = 3;
const PB_TYPE_FLOAT      = 4;
const PB_TYPE_INT        = 5;
const PB_TYPE_SIGNED_INT = 6;
const PB_TYPE_STRING     = 7;
const PB_TYPE_BOOL       = 8;

3) 属性字段的类型说明

required: 必须
optional: 可选
repeated: 多值

4) required/optional实现的方法

get{FIELD}()        // return field value
set{FIELD}($value)  // set field value to $value

5) 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

 

3. php如何使用protobuf

首先声明一个ProtobufMessage的子类,示例:

  1 <?php
  2 /**
  3  * 人
  4  * 声明一个ProtobufMessage的子类
  5  * 要实现ProtobufMessage里的抽象方法reset
  6  *
  7  */
  8 class Person extends ProtobufMessage{
  9     /**
 10      * 属性字段索引定义
 11      */
 12     const NAME = 1;     //姓名
 13     const AGE = 2;      //年龄
 14     const CARS = 3;     //拥有的汽车
 15 
 16     /**
 17      * type的定义值如下:
 18      *
 19      * 1:double; 2:fixed_32; 3:fixed_64; 4:float; 5:int; 6:signed int; 7:string; 8:bool;
 20      *
 21      */
 22     protected static $fields = array(
 23         self::NAME => array(
 24             'name' => 'name',
 25             'required' => true, //required:必填,optional:可选
 26             'type' => 7
 27         ),
 28         self::AGE => array(
 29             'name' => 'age',
 30             'required' => true,
 31             'type' => 5
 32         ),
 33         self::CARS => array(
 34             'name' => 'cars',
 35             'repeated' => true, //repeated:多值,数组或对象
 36             'type' => 7
 37         )
 38     );
 39 
 40     public function __construct() {
 41         $this->reset();
 42     }
 43 
 44     public function reset() {
 45         $this->values[self::NAME] = null;
 46         $this->values[self::AGE] = null;
 47         $this->values[self::CARS] = array();
 48     }
 49 
 50     public function fields() {
 51         return self::$fields;
 52     }
 53 
 54     /**
 55      * required/optional类型的字段
 56      * 要实现两个方法:  set{FIELD}($value)
 57      *                  get{FIELD}()
 58      *
 59      * 以上方法非必须
 60      */
 61 
 62     /**
 63      * 获得名字
 64      * @return string
 65      */
 66     public function getName() {
 67         return $this->get(self::NAME);
 68     }
 69 
 70     /**
 71      * 设置名字
 72      * @param string $name
 73      * @return bool
 74      */
 75     public function setName($name) {
 76         return $this->set(self::NAME, $name);
 77     }
 78 
 79     /**
 80      * 获得年龄
 81      * @return int
 82      */
 83     public function getAge() {
 84         return $this->get(self::AGE);
 85     }
 86 
 87     /**
 88      * 设置年龄
 89      * @param int $age
 90      * @return bool
 91      */
 92     public function setAge($age) {
 93         return $this->set(self::AGE, $age);
 94     }
 95 
 96     /**
 97      * repeated类型的字段
 98      * 要实现多值型的方法:  append{FIELD}($value)
 99      *                      clear{FIELD}()
100      *                      get{FIELD}()
101      *                      get{FIELD}At($index)
102      *                      get{FIELD}Count()
103      *                      get{FIELD}Iterator()
104      *
105      * 以上这些方法非必须,命名方式也非必须,但最好有个统一的命名规则
106      */
107 
108     /**
109      * 追加值
110      *
111      * @param string $car
112      * @return bool
113      */
114     public function appendCars($car) {
115         return $this->append(self::CARS, $car);
116     }
117 
118     /**
119      * 清除值
120      * @return bool
121      */
122     public function clearCars() {
123         return $this->clear(self::CARS);
124     }
125 
126     /**
127      * 获得值
128      * @return array
129      */
130     public function getCars() {
131         return $this->get(self::CARS);
132     }
133 
134     /**
135      * 获得某个索引的值
136      * @param int $index 数组索引值
137      * @return string
138     public function getCarsAt($index) {
139         return $this->get(self::CARS, $index);
140     }
141 
142     /**
143      * 获得数组的数量
144      * @return int
145      */
146     public function getCarsCount() {
147         return $this->count(self::CARS);
148     }
149 
150     /**
151      * 获得数组的迭代类
152      * @return ArrayIterator
153      */
154     public function getCarsIterator() {
155         return new ArrayIterator($this->get(self::CARS));
156     }
157 
158 }

使用姿势:

 1 <?php
 2 $person = new Person();
 3 $person->setName('Arno');
 4 $person->setAge(18);
 5 $person->appendCars('宝马');
 6 $person->appendCars('奔驰');
 7 
 8 $packed = $person->serializeToString(); //序列化成proto格式
 9 $cc = $person->getCarsCount();
10 var_dump($cc);
11 #file_put_contents('person.proto', $packed); //保存成文件或mysql的二进制字段里
12 
13 //以下为读过程
14 
15 $person->reset();
16 try {
17     $person->parseFromString($packed);
18 } catch ( Exception $e ) {
19     die('Upss.. there is a bug in this example');
20 }
21 
22 $person->dump(); //输出

 

4. 参考:

Google开发者官网: https://developers.google.com/protocol-buffers/

Google的Github官网: https://github.com/google/protobuf

PHP的Protobuf扩展官网: https://github.com/allegro/php-protobuf

 

posted @ 2016-02-14 17:10  imarno  阅读(1733)  评论(0)    收藏  举报