近来用YII2开发一个商城系统,里面用到有关RPC。考虑到YAR在这方面性能比较突出,就试着自己捣鼓一下。
总的来说,实现起来并不复杂,具体步骤如下。
准备工作
配置网站环境
安装yii2(高级版)
参考http://www.yiichina.com/doc/guide/2.0/start-installation
这里不再赘述。
配置 Nginx,设置两个测试域名。
server_name yii.test localhost;
RPC服务端
在 backend/controllers/ 下,新建文件 RpcController.php
<?php
namespace backend\controllers;
use Yii;
use common\controllers\CommonController;
use yii\web\Controller;
/**
* rpc controller
*/
class RpcController extends CommonController
{
/**
* 关闭csft
* @var string
* @access public
*/
public $enableCsrfValidation = false;
/**
* ip
* @var string
* @access private
*/
private $ipArr = ['127.0.0.1','192.168.1.110'];
/**
* 密码
* @var string
* @access private
*/
private $password = 'Add25f37';
/**
* 有效时间 秒
* @var string
* @access private
*/
private $activeTime = 1440;
/**
* 暂无说明
*
* @author Zhiqiang Guo
* @return void
* @throws Exception
* @access public
*/
public function actionIndex()
{
$request = Yii::$app->request;
//解密
$data = $this->rpcDecode($request->get('rpctoken'));
//权限认证
if (!$this->auth($data)) {
return;
}
try {
$server = new \Yar_Server(new $data['class']());
$server->handle();
} catch (Exception $e) {
return;
$e->getMessage();
}
// return $this->render('index');
}
/**
* 权限认证
*
* @author Zhiqiang Guo
* @return void
* @throws Exception
* @access private
*/
private function auth($param)
{
if (!$param) {
return false;
}
//验证IP
if (!in_array(Yii::$app->request->userIP, $this->ipArr)) {
return false;
}
//有效时间
if ((time() - $param['time']) > $this->activeTime) {
return false;
}
//验证密码
if ($param['password'] !== $this->password) {
return false;
}
if(empty($param['class'])){
return false;
}
return true;
}
/**
* 解密
*
* @author Zhiqiang Guo
* @return void
* @throws Exception
* @access private
*/
private function rpcDecode($str)
{
if ($str) {
return json_decode(base64_decode($str),true);
}
return [];
}
}
RPC客户端
在 common/ 新建目录 rpc,在 common/rpc/新建文件 YarApi.php
<?php
namespace common\rpc;
/**
* Yar rpc client
*
* @author 郭志强
* @return void
* @date: 2017-06-28
*
*/
class YarApi
{
/**
* 密码
* @var string
* @access private
*/
private $password = 'Add25f37';
/**
* 暂无说明
*
* @author Zhiqiang Guo
* @return void
* @throws Exception
* @access public
*/
public function api(array $condition)
{
$defult = [
// 'url' => 'http://yii.test/rpc/index/', //服务器URL
'url' => 'http://localhost/rpc/index/', //服务器URL
'class' => '', //class名称
];
$condition = array_merge($defult,$condition);
$data = [];
$data['time'] = time();
$data['password'] = $this->password;
$data['class'] = $condition['class'];
return new \Yar_Client("{$condition['url']}{$this->rpcEncode($data)}");
}
/**
* 加密
*
* @author Zhiqiang Guo
* @return void
* @throws Exception
* @access private
*/
private function rpcEncode ( array $data)
{
return base64_encode(json_encode($data));
}
}
美化URL
修改文件 backend/config/main.php
'urlManager' => [
'enablePrettyUrl' => true, //美化url==ture
'enableStrictParsing' => false, //不启用严格解析
'showScriptName' => false, //隐藏index.php
'rules' => [
'<controller:rpc>/<action:\w+>/<rpctoken:.+>' => '<controller>/<action>',
],
],
新建model 类
在目录 backend/models/,新建 Per.php
<?php
/**
* $Author: Zhiqiang Guo
* $Id: Per
* $date 2017/6/29
*/
namespace backend\models;
use Yii;
use yii\db;
use yii\base\Model;
use yii\db\ActiveRecord;
use yii\filters\VerbFilter;
use yii\filters\AccessControl;
use common\models\LoginForm;
/**
* 权限表的model类
*
* @category Custom
* @package Custom_Common
* @author name
*/
class Per extends ActiveRecord
{
/**
* 暂无说明
*
* @author name
* @return void
* @throws Exception
* @access public
*/
public function rules()
{
return [
];
}
/**
* 返回一个你要查询的表名
*
* @author name
* @return void
* @throws Exception
* @access public
*/
public static function tableName()
{
//表名
return 'system_per';
}
/**
* 查询权限的所有数据
*
* @author name
* @return void
* @throws Exception
* @access public
*/
public function SelAll()
{
$res=Per::find()->asArray()->All();
return $res;
}
}
测试
在目录 backend/controllers/, 新建 TestController.php
<?php
namespace backend\controllers;
use Yii;
use common\controllers\CommonController;
use yii\web\Controller;
use common\rpc\YarApi;
/**
* 测试
*
* @author Zhiqiang Guo
* @date 2017-07-02
*/
class TestController extends CommonController
{
/**
* No explanation
*
* @author Zhiqiang Guo
* @return void
* @throws Exception
* @access public
*/
public function actionIndex ()
{
$condition = ['class'=>'\backend\models\Per'];
$yar = new YarApi();
$model = $yar->api($condition);
$query = $model->SelAll();
echo "<pre>";
var_dump( $query);
echo "</pre>";
exit;
}
}
运行 http://yii.test/test/index, 正确的话,会有数据输出。
注意事项
第一,要正确配置urlManager,配置不正确,是无法实现RPC的。
第二,关闭CSFT ,这是一个坑。关闭整个controller的CSFT方法是,在控制器内加上
/**
* 关闭csft
* @var string
* @access public
*/
public $enableCsrfValidation = false;
希望本文能给需要的朋友带来一定帮助,再次感谢大家能花时间读完,如有什么问题或建议请回复。