在 Yii 2.0 中 RPC 的 ActiveDataFilter 实现,支持筛选参数等
1、在 api.pcs-stat.localhost 下,一个标准的 RESTful API。方法文件中的代码如下(一位同事所编写)。如图1
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | <?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 , ], ]); } } |
1 2 3 4 5 | 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
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | <?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
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 27 28 29 30 31 32 33 34 35 36 37 | <?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
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 | <?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
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 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | { "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": { } }, "_meta": { "totalCount": 8, "pageCount": 1, "currentPage": 1, "perPage": 8 } } } |
7、查看请求日志,本质上是先请求:api.pcs-api.localhost,再请求:rpc.pcs-stat.localhost。如图3
近期评论