在 Yii 2.0 上,RESTful 风格的 Web Service 服务的 API,POST 批量新建资源的实现
1、\api\rests\plan_task\CreateAction.php,具体实现可参考网址:https://github.com/yiisoft/yii2/blob/master/docs/guide-zh-CN/input-tabular-input.md ,代码如下:
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\plan_task; use Yii; use yii\base\Model; use yii\helpers\Url; use yii\web\ServerErrorHttpException; /** * CreateAction implements the API endpoint for creating a new model from the given data. * * For more details and usage information on CreateAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class CreateAction extends Action { /** * @var string the scenario to be assigned to the new model before it is validated and saved. */ public $scenario = Model::SCENARIO_DEFAULT; /** * Creates a new model. * @return \yii\db\ActiveRecordInterface the model newly created * @throws ServerErrorHttpException if there is any error when creating the model */ public function run() { if ($this->checkAccess) { call_user_func($this->checkAccess, $this->id); } // 当前用户的身份实例,未认证用户则为 Null $identity = Yii::$app->user->identity; /* @var $model \yii\db\ActiveRecord */ /* $model = new $this->modelClass([ 'scenario' => 'create', ]); */ $requestParams = Yii::$app->getRequest()->getBodyParams(); $count = count($requestParams); //创建一个初始的 $models 数组包含一个默认的模型 $scenario = 'create'; $models = [new $this->modelClass([ 'scenario' => $scenario, ])]; for($i = 1; $i < $count; $i++) { $models[] = new $this->modelClass([ 'scenario' => $scenario, ]); } // 批量填充模型属性 if (!Model::loadMultiple($models, $requestParams, '')) { return ['code' => 20010, 'message' => Yii::t('error', '20010')]; } foreach ($models as $key => $model) { $model->group_id = $identity->group_id; $model->config_column_id = $model->plan['config_column_id']; $model->create_user_id = $identity->id; $model->create_name = $identity->login_name; $model->exec_name = $model->userByExecUserId['login_name']; $model->task_data = serialize([]); $model->ended_at = time() + Yii::$app->params['planTaskExpire']; $models[$key] = $model; } // 批量验证模型 if (Model::validateMultiple($models)) { foreach ($models as $model) { $model->save(false); } $response = Yii::$app->getResponse(); $response->setStatusCode(201); } else { return ['code' => 20011, 'message' => Yii::t('error', '20011')]; } return ['code' => 10000, 'message' => Yii::t('success', '10006'), 'data' => ['items' => $models]]; } }
2、在 Postman 上,请求参数如图1
0[plan_id]:1 0[title]:早间新闻的标题1下的任务7 0[config_task_id]:2 0[exec_user_id]:8 0[place]:早间新闻的标题1下的地点7 0[task_info]:早间新闻的标题1下的内容7 1[plan_id]:1 1[title]:早间新闻的标题1下的任务8 1[config_task_id]:2 1[exec_user_id]:8 1[place]:早间新闻的标题1下的地点8 1[task_info]:早间新闻的标题1下的地点8
3、应前端的请求,添加表单名称,\api\rests\plan_task\CreateAction.php,代码如下
<?php /** * @link http://www.yiiframework.com/ * @copyright Copyright (c) 2008 Yii Software LLC * @license http://www.yiiframework.com/license/ */ namespace api\rests\plan_task; use Yii; use yii\base\Model; use yii\helpers\Url; use yii\web\ServerErrorHttpException; /** * 指派(创建任务) * * 1、请求参数列表 * (1)plan_id 必填,选题ID * (2)title 必填,任务标题 * (3)config_task_id 必填,任务配置(类型)ID * (4)exec_user_id 必填,执行用户ID * (5)place 必填,地点 * (6)task_info 必填,任务信息 * * 2、输入数据验证规则 * (1)必填:plan_id, title, config_task_id, exec_user_id, place, task_info; * (2)存在性:config_task_id 必须存在于任务配置模型中,且其状态为 1:启用; * (3)存在性:plan_id 必须存在于选题模型中,且其状态为 3:通过/5:指派; * (4)存在性:plan_id 选题所属栏目ID必须存在,且其状态为 1:启用; * (5)存在性:create_user_id 必须存在于选题所属栏目的人员配置模型中,且其状态为 1:启用; * (6)存在性:exec_user_id 必须存在于选题所属栏目的人员配置模型中,且其状态为 1:启用; * (7)默认值(''):'place', 'task_info'; * * 3、操作数据(事务) * (1)循环插入任务(传递 false 作为 [[save()]]的一个参数使其不会重复验证两次); * (2)批量插入任务步骤,创建批量 INSERT 命令(batchInsert); * (3)更新选题状态:指派; * * For more details and usage information on CreateAction, see the [guide article on rest controllers](guide:rest-controllers). * * @author Qiang Wang <shuijingwanwq@163.com> * @since 1.0 */ class CreateAction extends Action { /** * @var string the scenario to be assigned to the new model before it is validated and saved. */ public $scenario = Model::SCENARIO_DEFAULT; /** * Creates a new model. * @return \yii\db\ActiveRecordInterface the model newly created * @throws ServerErrorHttpException if there is any error when creating the model */ public function run() { if ($this->checkAccess) { call_user_func($this->checkAccess, $this->id); } // 当前用户的身份实例,未认证用户则为 Null $identity = Yii::$app->user->identity; /* @var $model \yii\db\ActiveRecord */ /* $model = new $this->modelClass([ 'scenario' => 'create', ]); */ $requestParams = Yii::$app->getRequest()->getBodyParams(); $formName = 'plan_task'; $count = count($requestParams[$formName]); //创建一个初始的 $models 数组包含一个默认的模型 $scenario = 'create'; $models = [new $this->modelClass([ 'scenario' => $scenario, ])]; for($i = 1; $i < $count; $i++) { $models[] = new $this->modelClass([ 'scenario' => $scenario, ]); } // 批量填充模型属性 if (!Model::loadMultiple($models, $requestParams, $formName)) { return ['code' => 20010, 'message' => Yii::t('error', '20010')]; } foreach ($models as $key => $model) { $model->group_id = $identity->group_id; $model->config_column_id = $model->planById['config_column_id']; $model->create_user_id = $identity->id; $model->create_name = $identity->login_name; $model->exec_name = $model->userByExecUserId['login_name']; $model->task_data = serialize([]); $model->ended_at = time() + Yii::$app->params['planTaskExpire']; $models[$key] = $model; } // 批量验证模型 if (Model::validateMultiple($models)) { $modelResult = $model->createMultiple($models); if (!$modelResult) { return ['code' => 20015, 'message' => Yii::t('error', '20015')]; } $response = Yii::$app->getResponse(); $response->setStatusCode(201); } else { foreach ($models as $model) { if ($model->hasErrors()) { $response = Yii::$app->getResponse(); $response->setStatusCode(422, 'Data Validation Failed.'); foreach ($model->getFirstErrors() as $message) { $firstErrors = $message; break; } return ['code' => 20004, 'message' => Yii::t('error', Yii::t('error', Yii::t('error', '20004'), ['firstErrors' => $firstErrors]))]; } } throw new ServerErrorHttpException('Failed to create the object for unknown reason.'); } foreach ($models as $key => $model) { $model->task_data = unserialize($model->task_data); $models[$key] = $model; } return ['code' => 10000, 'message' => Yii::t('success', '10006'), 'data' => ['items' => $models]]; } }
4、\common\logics\PlanTask.php,代码如下
/** * 批量指派(创建任务) * * @param $models * * @return bool the saved model or false if saving fails * @throws \Throwable */ public function createMultiple($models) { $transaction = Yii::$app->db->beginTransaction(); $time = time(); try { foreach ($models as $model) { if (!$model->save(false)) { throw new ServerErrorHttpException(Yii::t('error', '20015'), 20015); } /* 创建MySQL模型(选题任务步骤) */ $table = PlanTaskStep::tableName(); $columns = [ 'group_id', 'task_id', 'task_title', 'step_code', 'step_name', 'sort_order', 'updated_name', 'created_at', 'updated_at' ]; /* 将模型记录转换为索引数组 */ foreach ($model->configTaskSteps as $configTaskStep) { if ($configTaskStep->status == ConfigTaskStep::CONFIG_TASK_STEP_STATUS_ENABLE && $configTaskStep->is_default == 1) { $rows[] = [ $model->group_id, $model->id, $model->title, $configTaskStep->step_code, $configTaskStep->step_name, $configTaskStep->sort_order, $model->create_name, $time, $time, ]; } } } Yii::$app->db->createCommand()->batchInsert($table, $columns, $rows)->execute(); $transaction->commit(); return true; } catch (\Throwable $e) { $transaction->rollBack(); throw $e; } }
5、在 Postman 上,请求参数如图2
plan_task[0][plan_id]:2 plan_task[0][title]:选题2的任务6的标题 plan_task[0][config_task_id]:2 plan_task[0][exec_user_id]:187 plan_task[0][place]:选题2的任务6的地点 plan_task[0][task_info]:选题2的任务6的内容 plan_task[1][plan_id]:2 plan_task[1][title]:选题2的任务7的标题 plan_task[1][config_task_id]:2 plan_task[1][exec_user_id]:191 plan_task[1][place]:选题2的任务7的地点 plan_task[1][task_info]:选题2的任务7的内容
6、在 Postman 上,响应参数如图3
{ "code": 10000, "message": "指派(创建任务)成功", "data": { "items": [ { "plan_id": "2", "title": "选题2的任务6的标题", "config_task_id": "2", "exec_user_id": "187", "place": "选题2的任务6的地点", "task_info": "选题2的任务6的内容", "group_id": "015ce30b116ce86058fa6ab4fea4ac63", "config_column_id": 1, "create_user_id": 8, "create_name": "13281105967", "exec_name": "test3", "task_data": "a:0:{}", "ended_at": 1529047691, "created_at": 1526455691, "updated_at": 1526455691, "id": 37 }, { "plan_id": "2", "title": "选题2的任务7的标题", "config_task_id": "2", "exec_user_id": "191", "place": "选题2的任务7的地点", "task_info": "选题2的任务7的内容", "group_id": "015ce30b116ce86058fa6ab4fea4ac63", "config_column_id": 1, "create_user_id": 8, "create_name": "13281105967", "exec_name": "test4", "task_data": "a:0:{}", "ended_at": 1529047691, "created_at": 1526455692, "updated_at": 1526455692, "id": 38 } ] } }
近期评论