PHP安装Protobuf扩展及示例

ubuntu下PHP之protobuf扩展安装,使用示例

最近接触到需要使用google的Protocol Buffers数据传输,特作记录如下:

一、安装

参考github的开源扩展:https://github.com/allegro/php-protobuf/ 以下的“使用”是翻译自该说明文档

  1. 克隆代码
    git clone https://github.com/allegro/php-protobuf
    
  2. 进入代码目录
    cd php-protobuf
    
  3. 编译安装 PHP 扩展 (可参考: php.net)
    $ phpize
    $ ./configure
    $ make
    $ sudo make install

    这里默认安装到了

    可能会报错:Cannot find autoconf. Please check your autoconf installation and the $PHP_AUTOCONF environment variable. Then, rerun this script.

    原因:缺少autoconf,安装之!

    $ sudo apt-get install autoconf
  4. 开启PHP扩展
    # 请把下行代码添加到你的 php.ini
    extension=protobuf.so

    这里会有很多问题,首先需要查找你的PHP安装到了哪里(which php)然后从 php.ini 配置文件,或者 fpm 配置入手查找是否正确载入了PHP扩展。

    反正我是使用命令行,结果在第5步没有检测到,在phpinfo()中反而有。后来排查发现在 cli 模式下没有建立编译扩展的软链接导致的

  5. 检查是否安装成功
    重启Apache或者Nginx,和php-fpm

    $ sudo nginx -s reload
    $ sudo service php-fpm restart
    $ php -m | grep protobuf

    或者在phpinfo()  就可以看到 protobuff扩展

  6. 在代码目录下安装 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
    

    这里可能会报错说你的 protobuf-compiler 版本不能低于2.6,所以你还需要安装大于2.6的编译器.参见另一篇文章:为centos服务器安装protobuf2.6.1及以上
    安装完成后输入

    $protoc --version
    

    输出: libprotoc 2.6.1

    再次运行编译,编译后自动生成Foo.php文件。protoc-gen-php.php文件在你 git clone 的文件夹下

    注:如果你的xxx.proto文件比较复杂可能会生成多个php文件,你可以增加 -o 参数指定文件夹输出,以便于创建消息时引入

    php protoc-gen-php.php -o output_dir foo.proto
  3. 创建一个protobuf的消息,并给它赋值
    require_once Foo.php
    $foo = new Foo (); 
    $foo->setBar(1);
    $foo->setBaz('two');
    $foo->appendSpam(3.0);
    $foo->appendSpam(4.0);
  4. 序列化一个protobuf消息为 二进制 string
    $packed = $foo->serializeToString();
  5. 从二进制 string 解析一个消息
    $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();

到这里使用翻译结束

Author: thinkwei

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注