Window环境PHP7使用Protobuf开发详解
安装Protoc
用于生成PHP代码
下载地址: https://github.com/protocolbuffers/protobuf/releases
选择Window平台下载地址
这里选择最新版
https://github.com/protocolbuffers/protobuf/releases/download/v3.11.4/protoc-3.11.4-win64.zip
下载后选择一个目录解压, 这里解压到
D:\Program Files\protoc-3.11.4-win64
设置环境变量
查看是否安装成功
编写 protocol buffers 文件, 安装protoc解压目录的include包含一些样例
D:\Program Files\protoc-3.11.4-win64\include
这里简单编写一个User.proto
syntax = "proto3";package App.Bean;message User{int32 uid = 1;string username = 2;string nickname = 3;int32 age = 4;int32 sex = 5;
}
新建一个项目, E:\wamp64\www\wwwroot\gitroot\prototest
进入目录新建文件夹proto
把User.proto文件放在proto目录中
执行命令生成文件
protoc --php_out=. proto/User.proto
–php_out=.表示编译成PHP代码,放在当前目录(.),也可以指定文件夹。
protoc --php_out=mylib proto/User.proto
protoc还支持编译其他语言:
$ protoc | grep "=OUT_DIR"--cpp_out=OUT_DIR Generate C++ header and source.--csharp_out=OUT_DIR Generate C# source file.--java_out=OUT_DIR Generate Java source file.--js_out=OUT_DIR Generate JavaScript source.--objc_out=OUT_DIR Generate Objective C header and source.--php_out=OUT_DIR Generate PHP source file.--python_out=OUT_DIR Generate Python source file.--ruby_out=OUT_DIR Generate Ruby source file.
编译结果:
生成后的文件结构:
├── GPBMetadata
│ └── Proto
│ └── User.php
└── App
│ └── Bean
│ └── User.php
├── proto
│ └── User.proto
测试代码
$data = ['uid'=>1,'username'=>'Soul'];$userProto = new User($data);$userProto->setAge(20);$userProto->setSex(1);$str = $userProto->serializeToString(); print_r($userProto->serializeToJsonString());$userProto2= new User(); $userProto2->mergeFromString($str);
proto语法
官方文档: https://developers.google.com/protocol-buffers/docs/overview
也可以参考 Protobuf3语言指南 写得不错
1、proto3
proto 有proto3 和 proto2。proto3 比 proto2 支持更多语言但 更简洁。去掉了一些复杂的语法和特性,更强调约定而弱化语法。如果是首次使用 Protobuf ,建议使用 proto3 。详见参考文献说明。
需要在proto头部申明:
syntax = "proto3";
如果你没有指定这个,编译器会使用proto2。
2、注释
使用 //,示例:
message UserList {repeated User list = 1; //用户列表int32 page = 2; //分页int32 limit = 3; //分页条数
}
其中写在每个属性后面的注释在生产的代码里面有保留。
3、message
message类似于结构体的概念,最终编译为代码在PHP、JAVA里就是一个类,在golang里是结构体。每一个属性都会生成对应的getXXX、setXXX方法。
4、字段规则
repeated表示这个属性重复N次,在相对应的编程语言中通常是一个空的list。PHP里对应数组。
reserved表示标识号保留暂时不用。
message Foo {reserved 2, 15, 9 to 11;reserved "foo", "bar";
}
在消息定义中,每个字段都有唯一的一个数字标识符。这些标识符是用来在消息的二进制格式中识别各个字段的,一旦开始使用就不能够再改变。注:[1,15]之内的标识号在编码的时候会占用一个字节。[16,2047]之内的标识号则占用2个字节。所以应该为那些频繁出现的消息元素保留 [1,15]之内的标识号。**切记:要为将来有可能添加的、频繁出现的标识号预留一些标识号。**最小的标识号可以从1开始,最大到2^29 - 1, or 536,870,911。
5、支持的数据类型
.proto Type | Notes C++ Type | Java Type | Python Type[2] | Go Type | Ruby Type | C# Type | PHP Type |
---|---|---|---|---|---|---|---|
double | double | double | float | float64 | Float | double | float |
float | float | float | float | float32 | Float | float | float |
int32 | 使用变长编码,对于负值的效率很低,如果你的域有可能有负值,请使用sint64替代 | int32 | int | int | int32 | Fixnum 或者 Bignum(根据需要) | int |
uint32 | 使用变长编码 | uint32 | int | int/long | uint32 | Fixnum 或者 Bignum(根据需要) | uint |
uint64 | 使用变长编码 | uint64 | long | int/long | uint64 | Bignum | ulong |
sint32 | 使用变长编码,这些编码在负值时比int32高效的多 | int32 | int | int | int32 | Fixnum 或者 Bignum(根据需要) | int |
sint64 | 使用变长编码,有符号的整型值。编码时比通常的int64高效。 | int64 | long | int/long | int64 | Bignum | long |
fixed32 | 总是4个字节,如果数值总是比总是比228大的话,这个类型会比uint32高效。 | uint32 | int | int | uint32 | Fixnum 或者 Bignum(根据需要) | uint |
fixed64 | 总是8个字节,如果数值总是比总是比256大的话,这个类型会比uint64高效。 | uint64 | long | int/long | uint64 | Bignum | ulong |
sfixed32 | 总是4个字节 | int32 | int | int | int32 | Fixnum 或者 Bignum(根据需要) | int |
sfixed64 | 总是8个字节 | int64 | long | int/long | int64 | Bignum | long |
bool | bool | boolean | bool | bool | TrueClass/FalseClass | bool | boolean |
string | 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。 | string | String | str/unicode | string | String (UTF-8) | string |
bytes | 可能包含任意顺序的字节数据。 | string | ByteString | str | []byte | String (ASCII-8BIT) | ByteString |
6、默认值说明
string类型,默认值是空字符串
bytes类型,默认值是空bytes
bool类型,默认值是false
数字类型,默认值是0
枚举类型,默认值是第一个枚举值,即0
repeated修饰的属性,默认值是空.
7、枚举
使用enum关键字定义枚举,值必须从0开始:
enum Corpus {UNIVERSAL = 0;WEB = 1;IMAGES = 2;LOCAL = 3;NEWS = 4;PRODUCTS = 5;VIDEO = 6;
}
8、引用类型
上面的UserList就引用了User类型。大家可以看一下。
9、import
如果一个proto文件引用了另外一个proto文件,那么可以使用import关键字在头部申明:
import "User.proto";
10、Map类型
proto支持map属性类型的定义,语法如下:
map<key_type,value_type> map_field = N;
示例:
map<string, string> ext = 6; //扩展信息
这个map对于PHP来说就是关联数组,对于golang来说就是Map。
10、Any
Any类型允许包装任意的message类型,可以通过pack()和unpack()(方法名在不同的语言中可能不同)方法打包/解包:
import "google/protobuf/any.proto";message Response {google.protobuf.Any data = 1;
}
PHP开发的同学可能觉得Any没必要,因为数组里任何类型都可以放,但是对于强类型语言,数组里的值类型必须是一致的,使用Any类型可以解决这个问题。Any相当于把值包装了一层,这样都是Any类型。
11、服务定义
service UserService {// 方法名 方法参数 返回值rpc GetUser(Request) returns (Response);
}
这相当于定义了一个类,里面有一个对外的GetUser()方法。这个通常用于定义RPC服务,与gRPC结合使用。
12、从.proto文件生成了什么?
当用protocol buffer编译器来运行.proto文件时,编译器将生成所选择语言的代码,这些代码可以操作在.proto文件中定义的消息类型,包括获取、设置字段值,将消息序列化到一个输出流中,以及从一个输入流中解析消息。
PHP:每一个Message或者Enum生成一个类,另外还会生成GPBMetadata。
C++:编译器会为每个.proto文件生成一个.h文件和一个.cc文件,.proto文件中的每一个消息有一个对应的类。
Java:编译器为每一个消息类型生成了一个.java文件,以及一个特殊的Builder类(该类是用来创建消息类接口的)。
Python:Python编译器为.proto文件中的每个消息类型生成一个含有静态描述符的模块,该模块与一个元类(metaclass)在运行时(runtime)被用来创建所需的Python数据访问类。
go:编译器会位每个消息类型生成了一个.pd.go文件。
Ruby:编译器会为每个消息类型生成了一个.rb文件。
Objective-C:编译器会为每个消息类型生成了一个pbobjc.h文件和pbobjcm文件,.proto文件中的每一个消息有一个对应的类。
C#:编译器会为每个消息类型生成了一个.cs文件,.proto文件中的每一个消息有一个对应的类。
IDE插件
1、JetBrains PhpStorm 可以在插件里找到Protobuf安装,重启IDE后就支持proto格式语法了。
2、VScode 在扩展里搜索 Protobuf,安装即可。
3、protobuf的 php 扩展类在ide中没有提示,可将https://github.com/protocolbuffers/protobuf/tree/master/php/src 目录下载到本地,将此目录加到ide的include_path中即可。
Window环境PHP7使用Protobuf开发详解相关推荐
- php7的安装方法,php7 iis安装方法详解(图文)
php7 iis安装方法详解(图文) php7 iis安装方法:首先在官网下载PHP7:然后将其解压到合适的位置:接着找到"php.ini-development"文件,并将其后缀 ...
- 《Web前端开发精品课——HTML5 Canvas开发详解》——第一部分第二章节
本节书摘来自异步社区<Web前端开发精品课--HTML5 Canvas开发详解>一书中的第1部分,第2章,作者:莫振杰 著,更多章节内容可以访问云栖社区"异步社区"公众 ...
- 《HTML5 canvas开发详解(第2版)》——1.9 HTML5 Canvas对象
本节书摘来自异步社区<HTML5 canvas开发详解(第2版)>一书中的第1章,第1.9节,作者: [美]Steve Fulton , Jeff Fulton 更多章节内容可以访问云栖社 ...
- python区块链开发_Fabric区块链Python开发详解
Hyperledger Fabric是最流行的联盟区块链平台.Fabric区块链Python开发详解课程 涵盖Fabric区块链的核心概念.Fabric网络搭建.Node链码开发.Python应用开发 ...
- STM32开发 -- 惯导模块开发详解
如需转载请注明出处:https://juyou.blog.csdn.net/article/details/93476976 STM32开发 – GPS模块开发详解 这篇文章已经对于GPS模块开发讲得 ...
- 《Android游戏开发详解》一导读
前 言 Android游戏开发详解 作为对编程知之甚少或者毫无所知的初学者,开始学习Android游戏开发,可能会觉得就像是穿越陌生的星际的旅程.有太多的事情要尝试,太多的知识要学习,令人遗憾的是,还 ...
- NodeJS+Express+mySQL服务端开发详解
NodeJS+Express+mySQL服务端开发详解 随着NodeJS的发展,现在已经被很多人熟知,NodeJS已经成为了前端开发人员必备的技能.本文不会对NodeJS过多介绍 如果你感兴趣可以访问 ...
- 基于证书的WCF安全开发详解
基于证书的WCF安全开发详解 前几天成功建立起了一套基于证书的安全的WCF服务,很兴奋,现在做一下总结,希望大侠们指点,也希望能帮助到一些菜鸟,哈哈. 一.安全通信的基本过程 这里只做定性的理论上的分 ...
- 《Linux设备驱动开发详解》学习笔记一
Linux设备驱动开发详解学习笔记<一> 书名:<Linux设备驱动开发详解>第二版 主机环境:Linux version 2.6.25-14.fc9.i686@Fedora ...
- 《Android游戏开发详解》一2.2 设置开发机器
本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.2节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区 ...
最新文章
- 用《R数据科学》学习一套数据处理语法
- java多态性详解——父类引用子类对象
- java实现兵乓球比赛_C语言实现乒乓球比赛
- [bzoj 4066]简单题
- LINUX上安装openjdk
- 详解-黑莓7290激活教程
- 【MODIS】MODIS数据的常用下载源
- 中英文 织梦 html5,织梦dedecms如何做中英文多语言站点
- matlab求解vrp问题遗传算法,vrp问题(遗传算法vrp问题)
- MATLA矩阵、特征值相关备忘
- CentOS 8 Error: Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist
- 计算机DNS怎么配置,如何设置电脑的dns地址
- 数学符号“s.t.”的意义
- docker-tags 命令行获取docker远程仓库上指定镜像的tag列表
- bootstrap-datetimepicker时间控件
- 4.2 Pollard p-1算法
- 自制黑科技------桌面整理工具
- [08]ESP32+激光传感器VL53L1x移植与调试(附源码)
- Allegro174版本新功能介绍之和172版本兼容设置
- matlab二阶阻尼震荡衰减,二阶欠阻尼电路的零响应输入-MATLAB课程设计.doc
热门文章
- 中国工科研究生200多篇英文论文中最常见的习惯(The Most Common Habits from more than 200 English Papers written by Gradua)
- 有赞亿级订单同步的探索与实践
- Apche Kafka 的生与死 – failover 机制详解
- PID系统稳定性与零极点的关系
- Linux 别名设置,可一键登入服务器- alias
- matlab 内存不足
- ZeroClipBoard的诡异事件
- rmats2sashimiplot:可视化rmats的可变剪切结果
- CNVD-2020-10487复现(Apache Tomcat文件包含漏洞)
- 一阶二阶常微分方程解法