php如何使用protobuf3

简介

Google Protocol Buffer( 简称 Protobuf) 是 Google 公司内部的混合语言数据标准,目前已经正在使用的有超过 48,162 种报文格式定义和超过 12,183 个 .proto 文件。他们用于 RPC 系统和持续数据存储系统。

Protocol Buffers 是一种轻便高效的结构化数据存储格式,可以用于结构化数据串行化,或者说序列化。它很适合做数据存储或 RPC 数据交换格式。可用于通讯协议、数据存储等领域的语言无关、平台无关、可扩展的序列化结构数据格式。目前提供了 C++、Java、Python 三种语言的 API。

如果要看序列号解析原理也可参考:https://www.cnblogs.com/naci/p/5341433.html

客观的说:感觉protobuf对php支持的不是很好,写一些比较复杂的数据结构,还是比较麻烦的。也有可能是自己的不足吧。

 

安装protobuf

进入网址:https://github.com/protocolbuffers/protobuf/releases

下载对应自己需要的安装包。进行安装

进入解压的安装包,执行以下命令:

./configure
make && make install

执行以上命令之后,执行下面的命令 查看是否安装成功,如果没报错,会显示protobuf的版本
protoc --version

 

定义proto文件

 例如:hello.proto

syntax = "proto3";
package lm;

message helloworld
{
    int32 id = 1; // ID
    string str = 2; // str
    int32 opt = 3; // optional field
}

注意:这里采用的是proto3的语法,和proto2不太一样,requiredoptional的限定已经没有了,所有的字段都是可选的。proto3相比proto2有什么区别

 

编译生成php文件

使用上面安装成功的protobuf进行编译proto文件

protoc hello.prot --php_out=./ 

解释:
    --php_out :编译输出成php文件
    --python_out :编译输出成python文件
    
  

 这时会在当前目录下,生成一个GPBMetadata的文件夹和Lm的文件夹,此时查看lm文件夹下的helloworld.php文件

阅读下里面的代码,发现它use了Google\Protobuf下的类,这是一个PHP库,可以去下载:

https://github.com/google/protobuf/tree/master/php/src/Google/Protobuf

也可以用composer引入到项目中,推荐用composer引入,因为composer会帮你自动生成Autoloader

composer require google/protobuf

采用composer方式引入google/protobuf之后,项目中会出现一个vendor目录。在自己的代码中include vendor下的autoload.php,以及刚才生成的helloworld.php文件,就可以进行二进制的读写了

 

测试二进制读写

 写入二进制文件

<?php 
include 'vendor/autoload.php'; 
include 'GPBMetadata/Hello.php';
include 'Lm/Hello.php';

$from = new \Lm\helloworld(); 
$from->setId(1); 
$from->setStr('foo bar, this is a message'); 
$from->setOpt(29); 
$data = $from->serializeToString(); 
file_put_contents('data.bin', $data);

读取二进制文件

<?php 
include 'vendor/autoload.php'; 
include 'GPBMetadata/Hello.php';
include 'Lm/Hello.php';

$data = file_get_contents('data.bin'); 
$to = new \Lm\helloworld(); 
$to->mergeFromString($data); 
echo $to->getId() . PHP_EOL; 
echo $to->getStr() . PHP_EOL; 
echo $to->getOpt() . PHP_EOL;

其实写到这里,你可能会发现读取很麻烦,如果参数很多岂不是要一个个打印出来,所以我最后用是python进行解析的,一个方法就自动全部读取了。

 

python进行解析二进制文件

 编写test.py文件

# -*- coding: utf-8 -*-
import hello_pb2
import sys

helloworld = hello_pb2.helloworld()
f = open(sys.argv[1],'rb')
helloworld.ParseFromString(f.read())
print helloworld



解释:
    hello_pb2:为 protoc hello.proto --python_out=./ 命令编译所得
    
    执行该python文件的命令(后面的参数为data二进制文件的路径):python test.py ./data

以上就是整个作者使用的过程

 

*看到有人说安装php的protobuf扩展可以解决多个参数一次性打印问题

在这里我也写出方法,但是本人自己安装之后,在执行文件会报错,希望后来者给出建议

 

一、安装php的protobuf扩展

进入php的目录的bin目录下,一般都会发现有pecl命令,然后执行以下命令

./pecl install protobuf


按照提示,在php.ini文件中加入protobuf的扩展
重启php即可

二、安装完php扩展,读写二进制文件

//写入
public function encode($data){
    $fields = $this->fields();
    foreach ($fields as $key => $_item) {
        $field_name = $_item['name'];
        if(isset($data[$field_name])) {
            $this->set($key, $data[$field_name]);
        }
    }

    try {
        $packed = $this->serializeToString();
    } catch (\Exception $ex) {
        $data['fields'] = $fields;
        $data['error']  = $ex->getMessage();
        writeLog($data, 'encode_new_pb_failed');
        $packed = '';
    }

    return $packed;
}

//读取
public function decode($packed){
    try {
        $this->parseFromString($packed);

    } catch (\Exception $ex) {
        writeLog($ex->getMessage(), 'decode_new_pb_failed');
    }

    $data = array();
    $fields = $this->fields();
    foreach ($fields as $key => $_item) {
        $field_name = $_item['name'];
        $data[$field_name] = $this->get($key);
    }

    return $data;
}

基于安装扩展之后的操作,作者并没有成功,也没时间去调试,希望大家借鉴下即可。勿喷

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值