一.protoc 工具生成
1.1 安装依赖扩展
[详细教程]
1.2 使用protoc工具生成对应的php类
由于protobuf扩展封装在框架的extend目录下面,路径: /casualgame/extend/socket/protobuf
以生成一个person类为例:
step1:创建person的protobuf定义文件:persongpb.proto
syntax="proto3";
package extend.socket.protobuf.person;//person类的命名空间,跟框架路径定义一致
message Person{
string name=1;//姓名
int32 age=2;//年龄
bool sex=3;//性别
}
1
2
3
4
5
6
7
syntax="proto3";
packageextend.socket.protobuf.person;//person类的命名空间,跟框架路径定义一致
messagePerson{
stringname=1;//姓名
int32age=2;//年龄
boolsex=3;//性别
}
step2:
生成Person类
切换到/casualgame/extend/socket/protobuf目录
执行命令:
> protoc –php_out=./ persongpb.proto
说明:
第一个参数
php_out表示生成php类
–php_out=./ 表示把php类生成在当前目录下
第二个参数
persongpb.proto表示使用persongpb.proto定义文件
这样会在/casualgame/extend/socket/protobuf目录下创建
Extend/Socket/Protobuf/Person这几个新目录,并且我们想要的Person类在该目录下面。
把Peroson/Person.php复制到/casualgame/extend/socket/protobuf目录下即可。
step3:
通过composer注册psr4命名空间
第一步:配置composer.json
php
{
"require": {
"monolog/monolog": "1.0.*",
"overtrue/pinyin": "~4.0",
"google/protobuf": "^3.8"
},
"autoload": {
"psr-4": {
"Monolog\\": "src/",
"Extend\\": "extend/",
"Extend\\Socket\\Protobuf\\":"extend/socket/protobuf/",
"GPBMetadata\\":"extend/socket/protobuf/GPBMetadata/"
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
php
{
"require":{
"monolog/monolog":"1.0.*",
"overtrue/pinyin":"~4.0",
"google/protobuf":"^3.8"
},
"autoload":{
"psr-4":{
"Monolog\\":"src/",
"Extend\\":"extend/",
"Extend\\Socket\\Protobuf\\":"extend/socket/protobuf/",
"GPBMetadata\\":"extend/socket/protobuf/GPBMetadata/"
}
}
}
红色部分为新加的命名空间,跟Person.php中的命名空间一致。执行composer install
会在/casualgame/vendor/composer/autoload_psr4.php文件下生成命名空间配置:
框架在自动加载的时候根据命名空间别名帮我们加载到我们想加载的文件。
> PS:如果对composer使用不熟的要好好复习一下。
示例(php向goserver请求获取用户信息)
1)定义格式文件
server.proto
syntax="proto2";
package extend.socket.protobuf.server;//命名空间
message PhpPlayer
{
required int32 uid = 1;
repeated PhpFieldData fields = 2;
optional int32 ret = 3; //0:成功 1-失败
}
message PhpFieldData
{
required string fieldname = 1;//例如money diamond exp
optional int64 fieldvalue = 2;
}
message PhpBroad2Client
{
repeated int32 uids = 1;//广播用户id
required string data = 2;//广播数据 json格式
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
syntax="proto2";
packageextend.socket.protobuf.server;//命名空间
messagePhpPlayer
{
requiredint32uid=1;
repeatedPhpFieldDatafields=2;
optionalint32ret=3;//0:成功 1-失败
}
messagePhpFieldData
{
requiredstringfieldname=1;//例如money diamond exp
optionalint64fieldvalue=2;
}
messagePhpBroad2Client
{
repeatedint32uids=1;//广播用户id
requiredstringdata=2;//广播数据 json格式
}
PS:对protobuf语法不熟悉的研究一下。[传送门](https://colobu.com/2015/01/07/Protobuf-language-guide/ “传送门”)
具体用法test.php:
require_once 'PhpBroad2Client.php';//引入需要的protobuf工具类
require_once 'PhpFieldData.php';
require_once 'PhpPlayer.php';
$client = new \Serverpb\PhpBroad2Client();
$client->appendUids(10001);//设置PhpBroad2Client的uids值
$data = new \Serverpb\PhpFieldData();
$data->setFieldname("money");
$data->setFieldvalue(1000);
$player = new \Serverpb\PhpPlayer();
$player->setUid(10002);
$player->appendFields($data);
$player->setRet(1);
$packed = $player->serializeToString();
var_dump($packed);
$parsed = new \Serverpb\PhpPlayer();
try {
$parsed->parseFromString($packed);
} catch (Exception $ex) {
die('Oops.. there is a bug in this example, ' . $ex->getMessage());
}
$parsed->dump();
die("end");
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
require_once'PhpBroad2Client.php';//引入需要的protobuf工具类
require_once'PhpFieldData.php';
require_once'PhpPlayer.php';
$client=new\Serverpb\PhpBroad2Client();
$client->appendUids(10001);//设置PhpBroad2Client的uids值
$data=new\Serverpb\PhpFieldData();
$data->setFieldname("money");
$data->setFieldvalue(1000);
$player=new\Serverpb\PhpPlayer();
$player->setUid(10002);
$player->appendFields($data);
$player->setRet(1);
$packed=$player->serializeToString();
var_dump($packed);
$parsed=new\Serverpb\PhpPlayer();
try{
$parsed->parseFromString($packed);
}catch(Exception$ex){
die('Oops.. there is a bug in this example, '.$ex->getMessage());
}
$parsed->dump();
die("end");
?>
2)整合到框架中
执行以下命令:
> php /data/wwwroot/php-protobuf-0.12.4/protoc-gen-php.php server.proto
同样在/casualgame/extend/socket/protobuf/Extend/Socket/Protobuf/Server文件夹下会生成
PhpBroad2Client.php PhpFieldData.php PhpPlayer.php三个文件。把整个Server目录拷贝到
/casualgame/extend/socket/protobuf/ 目录下,使用的时候引入三个工具类的命名空间。
使用:
namespace extend\socket;
use Extend\Socket\Protobuf\Server\PhpBroad2Client;
use Extend\Socket\Protobuf\Server\PhpFieldData;
use Extend\Socket\Protobuf\Server\PhpPlayer;
class test{
public static function test(){
$client = new PhpBroad2Client();
$client->appendUids(10001);
$data = new PhpFieldData();
$data->setFieldname("money");
$data->setFieldvalue(1000);
$player = new PhpPlayer();
$player->setUid(10002);
$player->appendFields($data);
$player->setRet(1);
$packed = $player->serializeToString();
$parsed = new PhpPlayer();
try {
$parsed->parseFromString($packed);
} catch (Exception $ex) {
die('Oops.. there is a bug in this example, ' . $ex->getMessage());
}
$parsed->dump();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
namespaceextend\socket;
useExtend\Socket\Protobuf\Server\PhpBroad2Client;
useExtend\Socket\Protobuf\Server\PhpFieldData;
useExtend\Socket\Protobuf\Server\PhpPlayer;
classtest{
publicstaticfunctiontest(){
$client=newPhpBroad2Client();
$client->appendUids(10001);
$data=newPhpFieldData();
$data->setFieldname("money");
$data->setFieldvalue(1000);
$player=newPhpPlayer();
$player->setUid(10002);
$player->appendFields($data);
$player->setRet(1);
$packed=$player->serializeToString();
$parsed=newPhpPlayer();
try{
$parsed->parseFromString($packed);
}catch(Exception$ex){
die('Oops.. there is a bug in this example, '.$ex->getMessage());
}
$parsed->dump();
}
}
PS:如果提示找不到相关class的话,只需要去composer.json psr4选项注册对应的命名空间。