在 Yii 2.0 中 RPC 的 ActiveDataFilter 实现,支持筛选参数等
1、在 api.pcs-stat.localhost 下,一个标准的 RESTful API。方法文件中的代码如下(一位同事所编写)。如图1
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\data_plan_control_task; use common\logics\StatTask; use Yii; use api\models\Plan; use yii\data\ActiveDataProvider; use yii\data\ArrayDataProvider; use yii\base\InvalidConfigException; /** * 获取数据大屏的选题管控的任务统计列表:/data-plan-control-tasks ( data-plan-control-task/index ) * * For more details and usage information on IndexAction, see the [guide article on rest controllers](guide:rest-controllers). * */ class IndexAction extends \yii\rest\IndexAction { public $dataFilter = [ 'class' => 'yii\data\ActiveDataFilter', 'searchModel' => 'api\models\StatTaskSearch', 'attributeMap' => [ 'group_id' => '{{%stat_task}}.[[group_id]]', 'created_at' => '{{%stat_task}}.[[created_at]]', ], ]; /** * Prepares the data provider that should return the requested collection of the models. * @return array|object|ActiveDataProvider * @throws InvalidConfigException */ protected function prepareDataProvider() { $requestParams = Yii::$app->getRequest()->getQueryParams(); $filter = null; if ($this->dataFilter !== null) { $this->dataFilter = Yii::createObject($this->dataFilter); if ($this->dataFilter->load($requestParams)) { $filter = $this->dataFilter->build(); if ($filter === false) { $firstError = ''; foreach ($this->dataFilter->getFirstErrors() as $message) { $firstError = $message; break; } return ['code' => 224003, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '224003'), ['first_error' => $firstError]))]; } } } if ($this->prepareDataProvider !== null) { return call_user_func($this->prepareDataProvider, $this, $filter); } /* @var $modelClass Plan */ $modelClass = $this->modelClass; // 任务数量 $statTask = StatTask::find()->select('sum(plan_task_sum) as plan_task_sum'); if (!empty($filter)) { $statTask->andFilterWhere($filter); } $statTask = $statTask->one(); $planTaskCount = $statTask->plan_task_sum; if(empty($planTaskCount)){ $planTaskInfo = []; }else{ // 任务信息 $planTaskInfo = StatTask::find() ->select([ StatTask::tableName() . '.name', 'sum('.StatTask::tableName().'.plan_task_sum)'.' as planTaskSum', ]) ->groupBy(StatTask::tableName() . '.name') ->orderBy(['planTaskSum' => SORT_DESC]); if (!empty($filter)) { $planTaskInfo->andFilterWhere($filter); } $planTaskInfo = $planTaskInfo->asArray()->all(); $num = 0; foreach($planTaskInfo as $key=>$value){ $planTaskInfo[$key]['planTaskSum'] = (int)$value['planTaskSum']; $proportion = (float)sprintf("%.4f", $planTaskInfo[$key]['planTaskSum']/$planTaskCount); $planTaskInfo[$key]['proportion'] = $proportion; if($value == end($planTaskInfo)) { $planTaskInfo[$key]['proportion'] = 1 - $num; }else{ $num = $num + $planTaskInfo[$key]['proportion']; } } } // 设置每页资源数量总数 // $count = 20; // $requestParams['per-page'] = $count; return Yii::createObject([ 'class' => ArrayDataProvider::className(), 'allModels' => $planTaskInfo, 'pagination' => [ 'params' => $requestParams, ], 'sort' => [ 'params' => $requestParams, ], ]); } }
Opening DB connection: mysql:host=62.234.135.47;dbname=pcs_stat SELECT sum(plan_task_sum) AS `plan_task_sum` FROM `ps_stat_task` WHERE ((`ps_stat_task`.`created_at` >= '1588756760') AND (`ps_stat_task`.`created_at` <= '1589880664')) AND (`ps_stat_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63'); SELECT `ps_stat_task`.`name`, sum(`ps_stat_task`.plan_task_sum) AS `planTaskSum` FROM `ps_stat_task` WHERE ((`ps_stat_task`.`created_at` >= '1588756760') AND (`ps_stat_task`.`created_at` <= '1589880664')) AND (`ps_stat_task`.`group_id`='015ce30b116ce86058fa6ab4fea4ac63') GROUP BY `ps_stat_task`.`name` ORDER BY `planTaskSum` DESC;
2、现在计划将此接口迁移至 api.pcs-api.localhost 下,此时,api.pcs-api.localhost 为 RPC 客户端,api.pcs-stat.localhost 为 RPC 服务端。参考:https://www.shuijingwanwq.com/2020/06/23/4273/ 。
3、新建 RPC 服务端文件,rpc/controllers/DataPlanControlTaskController.php
<?php /** * Created by PhpStorm. * User: Qiang Wang * Date: 2020/09/01 * Time: 10:50 */ namespace rpc\controllers; use Yii; use rpc\models\StatTask; use yii\base\InvalidConfigException; /** * DataPlanControlTask Controller * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class DataPlanControlTaskController extends ServerController { public $dataFilter = [ 'class' => 'yii\data\ActiveDataFilter', 'searchModel' => 'rpc\models\StatTaskSearch', ]; /** * 获取数据大屏的选题管控的任务统计列表 * * @param array $data 数据 * * @param string $version 版本号(次版本号与修订号) * 格式如下: * 2.3 * * @param string $language 区域和语言 * 格式如下: * en-US * * @return array * @throws InvalidConfigException */ public function actionIndex(array $data = [], string $version = '', string $language = '') { if (!empty($language)) { Yii::$app->language = $language; } $filter = null; if ($this->dataFilter !== null) { $this->dataFilter = Yii::createObject($this->dataFilter); if ($this->dataFilter->load($data)) { $filter = $this->dataFilter->build(); if ($filter === false) { $firstError = ''; foreach ($this->dataFilter->getFirstErrors() as $message) { $firstError = $message; break; } return ['code' => 230003, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '230003'), ['first_error' => $firstError]))]; } } } /* @var $modelClass StatTask */ $modelClass = $this->modelClass; // 任务数量 $statTask = $modelClass::find()->select('sum(plan_task_sum) as plan_task_sum'); if (!empty($filter)) { $statTask->andFilterWhere($filter); } $statTask = $statTask->one(); $planTaskCount = $statTask->plan_task_sum; if (empty($planTaskCount)) { $planTaskInfo = []; } else { // 任务信息 $planTaskInfo = StatTask::find() ->select([ StatTask::tableName() . '.name', 'sum('.StatTask::tableName().'.plan_task_sum)'.' as planTaskSum', ]) ->groupBy(StatTask::tableName() . '.name') ->orderBy(['planTaskSum' => SORT_DESC]); if (!empty($filter)) { $planTaskInfo->andFilterWhere($filter); } $planTaskInfo = $planTaskInfo->asArray()->all(); $num = 0; foreach ($planTaskInfo as $key => $value) { $planTaskInfo[$key]['planTaskSum'] = (int) $value['planTaskSum']; $proportion = (float) sprintf("%.4f", $planTaskInfo[$key]['planTaskSum'] / $planTaskCount); $planTaskInfo[$key]['proportion'] = $proportion; if ($value == end($planTaskInfo)) { $planTaskInfo[$key]['proportion'] = 1 - $num; } else { $num = $num + $planTaskInfo[$key]['proportion']; } } } return ['code' => 10000, 'message' => Yii::t('success', '10000'), 'data' => $planTaskInfo]; } }
4、新建 RPC 客户端的模型文件,common/logics/rpc/stat/StatTask.php
<?php namespace common\logics\rpc\stat; use Yii; use common\logics\rpc\Model; /** * 任务统计 */ class StatTask extends Model { const CONTROLLER_ID = 'data-plan-control-task'; // 控制器ID /** * 获取数据大屏的选题管控的任务统计列表 * * @param array $data 数据 * * @param string $version 版本号(次版本号与修订号) * 格式如下: * 2.3 * * @param string $language 区域和语言 * 格式如下: * en-US * * @return mixed * @throws \Exception */ public function index(array $data, string $version, string $language) { $actionId = 'index'; return self::client(self::CONTROLLER_ID, $actionId)->$actionId($data, $version, $language); } }
5、新建 RPC 客户端的方法文件,api/rests/data_plan_control_task/IndexAction.php
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\data_plan_control_task; use Yii; use api\models\rpc\stat\StatTask; use yii\data\ActiveDataProvider; use yii\data\ArrayDataProvider; use yii\base\InvalidConfigException; use yii\web\ServerErrorHttpException; /** * 获取数据大屏的选题管控的任务统计列表:/data-plan-control-tasks(data-plan-control-task/index) * * For more details and usage information on IndexAction, see the [guide article on rest controllers](guide:rest-controllers). * */ class IndexAction extends \yii\rest\IndexAction { public $dataFilter = [ 'class' => 'yii\data\ActiveDataFilter', 'searchModel' => 'api\models\StatTaskSearch', ]; /** * Prepares the data provider that should return the requested collection of the models. * @return array|mixed|object|ActiveDataProvider * @throws InvalidConfigException * @throws ServerErrorHttpException */ protected function prepareDataProvider() { $requestParams = Yii::$app->getRequest()->getQueryParams(); $filter = null; if ($this->dataFilter !== null) { $this->dataFilter = Yii::createObject($this->dataFilter); if ($this->dataFilter->load($requestParams)) { $filter = $this->dataFilter->build(); if ($filter === false) { $firstError = ''; foreach ($this->dataFilter->getFirstErrors() as $message) { $firstError = $message; break; } return ['code' => 224003, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '224003'), ['first_error' => $firstError]))]; } } } if ($this->prepareDataProvider !== null) { return call_user_func($this->prepareDataProvider, $this, $filter); } /* @var $modelClass StatTask */ $modelClass = $this->modelClass; // 内容协商 $response = Yii::$app->response; $acceptParams = $response->acceptParams; if (isset($acceptParams['version'])) { $version = $acceptParams['version']; } else { $version = ''; } // 获取数据大屏的选题管控的任务统计列表 $rpcStatStatTask = new $modelClass(); $data = $rpcStatStatTask->index($requestParams, $version, Yii::$app->language); if ($data['code'] !== 10000) { throw new ServerErrorHttpException(Yii::t('error', Yii::t('error', Yii::t('error', '202087'), ['code' => $data['code'], 'message' => $data['message']])), 202087); } // 设置每页资源数量默认为资源总数 $count = count($data['data']); if ($count !== 0) { $requestParams['per-page'] = $count; } return Yii::createObject([ 'class' => ArrayDataProvider::className(), 'allModels' => $data['data'], 'pagination' => [ 'params' => $requestParams, ], 'sort' => [ 'params' => $requestParams, ], ]); } }
6、分页参数的支持,有待于后续实现。此接口无需要支持分页参数的自定义。GET 请求:http://api.pcs-api.localhost/v1/data-plan-control-tasks?login_id=2e368664c41b8bf511bcc9c65d86dbc3&login_tid=d31652b0f940b810da05d9755d20c7a1&filter[created_at][gte]=1588756760&filter[created_at][lte]=1589880664&filter[group_id]=015ce30b116ce86058fa6ab4fea4ac63 。符合预期。如图2
{ "code": 10000, "message": "获取数据大屏的选题管控的任务统计列表成功", "data": { "items": [ { "name": "采访任务", "plan_task_sum": 17, "proportion": 0.2537 }, { "name": "互联网发布", "plan_task_sum": 14, "proportion": 0.209 }, { "name": "自定义一", "plan_task_sum": 13, "proportion": 0.194 }, { "name": "手动任务", "plan_task_sum": 9, "proportion": 0.1343 }, { "name": "电视播出", "plan_task_sum": 8, "proportion": 0.1194 }, { "name": "自定义二", "plan_task_sum": 3, "proportion": 0.0448 }, { "name": "自定义八", "plan_task_sum": 2, "proportion": 0.0299 }, { "name": "自定义六", "plan_task_sum": 1, "proportion": 0.0149 } ], "_links": { "self": { "href": "http://api.pcs-api.localhost/v1/data-plan-control-tasks?login_id=2e368664c41b8bf511bcc9c65d86dbc3&login_tid=d31652b0f940b810da05d9755d20c7a1&filter%5Bcreated_at%5D%5Bgte%5D=1588756760&filter%5Bcreated_at%5D%5Blte%5D=1589880664&filter%5Bgroup_id%5D=015ce30b116ce86058fa6ab4fea4ac63&page=1&per-page=8" } }, "_meta": { "totalCount": 8, "pageCount": 1, "currentPage": 1, "perPage": 8 } } }
7、查看请求日志,本质上是先请求:api.pcs-api.localhost,再请求:rpc.pcs-stat.localhost。如图3
近期评论