首页 > 编程 > PHP > 正文

Yii2中Restful API原理实例分析

2020-03-22 16:47:26
字体:
来源:转载
供稿:网友
本文实例分析了Yii2中Restful API原理。分享给大家供大家参考,具体如下:Yii2 有个很重要的特性是对 Restful API的默认支持, 通过短短的几个配置就可以实现简单的对现有Model的RESTful API这里通过分析rest部分源码,简单剖析下yii2 实现 restful 的原理,并通过一些定制实现 对 关联模型的RESTful api 操作。~ 代表 extends from 的关系| | rest/
| | |-Action.php ~ `/yii/base/Action`
| | |-Controller.php ~ `/yii/web/Controller`
| | | |-ActiveController.php ~ `rest/Controller`
| | |-Serializer.php ~ `yii/base/Component`
| | |-UrlRule.php ~ `yii/web/CompositeUrlRule`
| | |-CreateAction.php ~ `rest/Action`
| | |-DeleteAction.php ~ `rest/Action`
| | |-IndexAction.php ~ `rest/Action`
| | |-OptionsAction.php ~ `rest/Action`
| | |-UpdateAction.php ~ `rest/Action`
| | |-ViewAction.php ~ `rest/Action`1. rest/Controller ~ /yii/web/ControllerController是 RESTful API 控制器类的基类它在一个API请求的控制周期中一次实现了下面的步骤 1~5:① 解析响应的内容格式
② 校验请求方法
③ 检验用户权限
④ 限制速度
⑤ 格式化响应数据use yii/filters/auth/CompositeAuth;use yii/filters/ContentNegotiator;use yii/filters/RateLimiter;use yii/web/Response;use yii/filters/VerbFilter; * Controller is the base html' target='_blank'>class for RESTful API controller classes. * Controller implements the following steps in a RESTful API request handling cycle * 1. Resolving response format (see [[ContentNegotiator]]); * 2. Validating request method (see [[verbs()]]). * 3. Authenticating user (see [[/yii/filters/auth/AuthInterface]]); * 4. Rate limiting (see [[RateLimiter]]); * 5. Formatting response data (see [[serializeData()]])behaviors contentNegotiator verbFilter authenticator rateLimiterafterAction serializeData Yii::createObject($this- serializer)- serialize($data)verbs []class Controller extends /yii/web/Controller public $serializer = 'yii/rest/Serializer'; public $enableCsrfValidation = false; public function behaviors() return [ 'contentNegotiator' = [ 'class' = ContentNegotiator::className(), 'formats' = [ 'application/json' = Response::FORMAT_JSON, 'application/xml' = Response::FORMAT_XML, 'verbFilter' = [ 'class' = VerbFilter::className(), 'actions' = $this- verbs(), 'authenticator' = [ 'class' = CompositeAuth::className(), 'rateLimiter' = [ 'class' = RateLimiter::className(), public function verbs() return []; public function serializeData($data) return Yii::createObject($this- serializer)- serialize($data); public function afterAction($action, $result) $result = parent::afterAction($action, $result); return $this- serializeData($result);2. rest/ActiveController ~ rest/ControllerActiveController 实现了一系列的和 ActiveRecord 互通数据的RESTful方法ActiveRecord 的类名由 modelClass 变量指明, yii/db/ActiveRecordInterface 默认的, 支持下面的方法:* - `index`: list of models
* - `view`: return the details of a model
* - `create`: create a new model
* - `update`: update an existing model
* - `delete`: delete an existing model
* - `options`: return the allowed HTTP methods可以通过覆盖 actions() 并且 unsetting 响应的 action 来禁用这些默认的动作。要增加一个新的动作, 覆盖 actions() 向其末尾增加一个新的 action class 或者 是一个新的 action method注意一点,确保你同时也覆盖了 verbs() 方法来声明这个新的动作支持那些HTTP Method也需要覆盖checkAccess() 来检查当前用户是否有权限来执行响应的某个动作。根据上面的说明再写一遍 Controllerclass ActiveController extends Controller public #modelClass; public $updateScenario = Model::SCENARIO_DEFAULT; public $createScenario = Model::SCENARIO_DEFAULT; public function init() parent::init(); if($this- modelClass == null){ throw new InvalidConfigException('The "modelClass" property must be set.'); public function actions() return [ 'index' = [ 'class' = 'app/controllers/rest/IndexAction', 'modelClass' = $this- modelClass, 'checkAccess' = [$this, 'checkAccess'], 'view'... 'create'... 'update'... 'delete'... 'options'... protected function verbs() return [ 'index' = ['GET', 'HEAD'], 'view' = ['GET', 'HEAD'], 'create' = ['POST'], 'update' = ['PUT', 'PATCH'], 'delete' = ['DELETE'], public function checkAccess($action, $model=null, $params = [])下面来实现一个继承自 这个rest/ActiveController的 News 控制器:namespace app/controllers;use app/controllers/rest/ActiveController; #刚才这个AC,我从yii/rest下面拷贝了一份出来class NewsController extends ActiveController public $modelClass ='app/models/News';定义到这里就足够实现 rest/ActiveController 里面的默认方法了
下面来覆盖下,实现一些定制的方法class NewsController extends ActiveController public $modelClass = 'app/models/News'; #定制serializer #public $serializer = 'yii/rest/Serializer'; public $serializer = [ 'class' = 'app/controllers/rest/Serializer', 'collectionEnvelope' = 'items', public function behaviors() $be = ArrayHelper::merge( parent::behaviors(), 'verbFilter' = [ 'class' = VerbFilter::className(), 'actions' = [ 'index' = ['get'], 'authenticator' = [ 'class' = CompositeAuth::className(), 'authMethods' = [ HttpBasicAuth::className(), HttpBearerAuth::className(), QueryParamAuth::className(), 'contentNegotiator' = [ 'class' = ContentNegotiator::className(), 'formats' = [ 'text/html' = Response::FORMAT_HTML, 'access' = [ 'class' = AccessControl::className(), 'only' = ['view'], 'rules' = [ 'actions' = ['view'], 'allow' = false, 'roles' = ['@'], return $be; public function checkAccess()3. 定制Actions如果要对 Actions 进行大的改动,建议拷贝一份出来,不要使用原始的 yii/rest/XXXAction命名空间我这里以要实现对related models进行 CURD 操作为目标进行大的改动Action在定制各个action之前, 先看看它们的基类 rest/Action, 主要是一个 findModel的方法class Action extend /yii/base/Action public $modelClass; public $findModel; public $checkAccess; public function init() if($this- modelClass == null) { throw new InvalidConfigException(get_class($this). '::$modelClass must be set'); public function findModel($id) if($this- findModel !== null) { return call_user_func($this- findModel, $id, $this); $modelClass = $this- modelClass; $keys = $modelClass::primaryKey(); if(count($keys) 1) { $values = explode(',', $id); if.. } elseif($id !== null) { $model = $modelClass::findOne($id); if(isset($model)){ return $model; }else { throw new NotFoundHttpException("Object not found: $id");viewview 动作不需要改动,因为 model 有 getRelated 的自有机制class ViewAction extend Action public function run($id) $model = $this- findModel($id); if($this- checkAccess) { call_user_func($this- checkAccess, $this- id, $model);updatepublic function run($id) /* @var $model ActiveRecord */ $model = $this- findModel($id); if ($this- checkAccess) { call_user_func($this- checkAccess, $this- id, $model); $model- scenario = $this- scenario; $model- load(Yii::$app- getRequest()- getBodyParams(), ''); $model- save(); return $model;经过改造后,需要满足对关联模型的update动作public function run($id) /* @var $model ActiveRecord */ $model = $this- findModel($id); if ($this- checkAccess) { call_user_func($this- checkAccess, $this- id, $model); $model- scenario = $this- scenario; * x-www-form-urlencoded key= value * image mmmmmmmm * link nnnnnnnnnn * newsItem[title]= ttttttttttt , don't use newsItem["title"] * newsItem[body]= bbbbbbbbbbb * don't use newsItem= array("title":"tttttt","body":"bbbbbbb") * don't use newsItem= {"title":"ttttttt","body":"bbbbbbbb"} $newsItem = Yii::$app- getRequest()- getBodyParams()['newsItem']; Array [title] = ttttttttttt [body] = bbbbbbbbbbb $model- newsItem- load($newsItem, ''); #$model- newsItem- load(Yii::$app- getRequest()- getBodyParams(), ''); #print_R($model- newsItem);exit; #print_R($model- newsItem);exit; if($model- save()) $model- load(Yii::$app- getRequest()- getBodyParams(), ''); $model- newsItem- save(); return $model;这里还应该对 newsItem save 失败 的情况进行处理,暂且不处理。更多关于Yii相关内容感兴趣的读者可查看本站专题:《Yii框架入门及常用技巧总结》、《php优秀开发框架总结》、《smarty模板入门基础教程》、《php面向对象程序设计入门教程》、《php字符串(string)用法总结》、《php+mysql数据库操作入门教程》及《php常见数据库操作技巧汇总》希望本文所述对大家基于Yii框架的PHP程序设计有所帮助。PHP教程

郑重声明:本文版权归原作者所有,转载文章仅为传播更多信息之目的,如作者信息标记有误,请第一时间联系我们修改或删除,多谢。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表