安装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开发详解相关推荐

  1. php7的安装方法,php7 iis安装方法详解(图文)

    php7 iis安装方法详解(图文) php7 iis安装方法:首先在官网下载PHP7:然后将其解压到合适的位置:接着找到"php.ini-development"文件,并将其后缀 ...

  2. 《Web前端开发精品课——HTML5 Canvas开发详解》——第一部分第二章节

    本节书摘来自异步社区<Web前端开发精品课--HTML5 Canvas开发详解>一书中的第1部分,第2章,作者:莫振杰 著,更多章节内容可以访问云栖社区"异步社区"公众 ...

  3. 《HTML5 canvas开发详解(第2版)》——1.9 HTML5 Canvas对象

    本节书摘来自异步社区<HTML5 canvas开发详解(第2版)>一书中的第1章,第1.9节,作者: [美]Steve Fulton , Jeff Fulton 更多章节内容可以访问云栖社 ...

  4. python区块链开发_Fabric区块链Python开发详解

    Hyperledger Fabric是最流行的联盟区块链平台.Fabric区块链Python开发详解课程 涵盖Fabric区块链的核心概念.Fabric网络搭建.Node链码开发.Python应用开发 ...

  5. STM32开发 -- 惯导模块开发详解

    如需转载请注明出处:https://juyou.blog.csdn.net/article/details/93476976 STM32开发 – GPS模块开发详解 这篇文章已经对于GPS模块开发讲得 ...

  6. 《Android游戏开发详解》一导读

    前 言 Android游戏开发详解 作为对编程知之甚少或者毫无所知的初学者,开始学习Android游戏开发,可能会觉得就像是穿越陌生的星际的旅程.有太多的事情要尝试,太多的知识要学习,令人遗憾的是,还 ...

  7. NodeJS+Express+mySQL服务端开发详解

    NodeJS+Express+mySQL服务端开发详解 随着NodeJS的发展,现在已经被很多人熟知,NodeJS已经成为了前端开发人员必备的技能.本文不会对NodeJS过多介绍 如果你感兴趣可以访问 ...

  8. 基于证书的WCF安全开发详解

    基于证书的WCF安全开发详解 前几天成功建立起了一套基于证书的安全的WCF服务,很兴奋,现在做一下总结,希望大侠们指点,也希望能帮助到一些菜鸟,哈哈. 一.安全通信的基本过程 这里只做定性的理论上的分 ...

  9. 《Linux设备驱动开发详解》学习笔记一

    Linux设备驱动开发详解学习笔记<一> 书名:<Linux设备驱动开发详解>第二版 主机环境:Linux version 2.6.25-14.fc9.i686@Fedora ...

  10. 《Android游戏开发详解》一2.2 设置开发机器

    本节书摘来异步社区<Android游戏开发详解>一书中的第2章,第2.2节,作者: [美]Jonathan S. Harbour 译者: 李强 责编: 陈冀康,更多章节内容可以访问云栖社区 ...

最新文章

  1. 用《R数据科学》学习一套数据处理语法
  2. java多态性详解——父类引用子类对象
  3. java实现兵乓球比赛_C语言实现乒乓球比赛
  4. [bzoj 4066]简单题
  5. LINUX上安装openjdk
  6. 详解-黑莓7290激活教程
  7. 【MODIS】MODIS数据的常用下载源
  8. 中英文 织梦 html5,织梦dedecms如何做中英文多语言站点
  9. matlab求解vrp问题遗传算法,vrp问题(遗传算法vrp问题)
  10. MATLA矩阵、特征值相关备忘
  11. CentOS 8 Error: Failed to download metadata for repo ‘appstream‘: Cannot prepare internal mirrorlist
  12. 计算机DNS怎么配置,如何设置电脑的dns地址
  13. 数学符号“s.t.”的意义
  14. docker-tags 命令行获取docker远程仓库上指定镜像的tag列表
  15. bootstrap-datetimepicker时间控件
  16. 4.2 Pollard p-1算法
  17. 自制黑科技------桌面整理工具
  18. [08]ESP32+激光传感器VL53L1x移植与调试(附源码)
  19. Allegro174版本新功能介绍之和172版本兼容设置
  20. matlab二阶阻尼震荡衰减,二阶欠阻尼电路的零响应输入-MATLAB课程设计.doc

热门文章

  1. 中国工科研究生200多篇英文论文中最常见的习惯(The Most Common Habits from more than 200 English Papers written by Gradua)
  2. 有赞亿级订单同步的探索与实践
  3. Apche Kafka 的生与死 – failover 机制详解
  4. PID系统稳定性与零极点的关系
  5. Linux 别名设置,可一键登入服务器- alias
  6. matlab 内存不足
  7. ZeroClipBoard的诡异事件
  8. rmats2sashimiplot:可视化rmats的可变剪切结果
  9. CNVD-2020-10487复现(Apache Tomcat文件包含漏洞)
  10. 一阶二阶常微分方程解法