国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 語言 > PHP > 正文

Yii2中Restful API原理實(shí)例分析

2024-05-04 23:48:48
字體:
供稿:網(wǎng)友

本文實(shí)例分析了Yii2中Restful API原理。分享給大家供大家參考,具體如下:

Yii2 有個(gè)很重要的特性是對 Restful API的默認(rèn)支持, 通過短短的幾個(gè)配置就可以實(shí)現(xiàn)簡單的對現(xiàn)有Model的RESTful API

這里通過分析rest部分源碼,簡單剖析下yii2 實(shí)現(xiàn) restful 的原理,并通過一些定制實(shí)現(xiàn) 對 關(guān)聯(lián)模型的RESTful api 操作。

~ 代表 extends from 的關(guān)系

| | 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/Controller

Controller是 RESTful API 控制器類的基類

它在一個(gè)API請求的控制周期中一次實(shí)現(xiàn)了下面的步驟 1~5:

① 解析響應(yīng)的內(nèi)容格式
② 校驗(yàn)請求方法
③ 檢驗(yàn)用戶權(quán)限
④ 限制速度
⑤ 格式化響應(yīng)數(shù)據(jù)

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 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/Controller

ActiveController 實(shí)現(xiàn)了一系列的和 ActiveRecord 互通數(shù)據(jù)的RESTful方法

ActiveRecord 的類名由 modelClass 變量指明, yii/db/ActiveRecordInterface ???

默認(rèn)的, 支持下面的方法:

 * - `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 響應(yīng)的 action 來禁用這些默認(rèn)的動(dòng)作。

要增加一個(gè)新的動(dòng)作, 覆蓋 actions() 向其末尾增加一個(gè)新的 action class 或者 是一個(gè)新的 action method

注意一點(diǎn),確保你同時(shí)也覆蓋了 verbs() 方法來聲明這個(gè)新的動(dòng)作支持那些HTTP Method

也需要覆蓋checkAccess() 來檢查當(dāng)前用戶是否有權(quán)限來執(zhí)行響應(yīng)的某個(gè)動(dòng)作。

根據(jù)上面的說明再寫一遍 Controller

class 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 = [])  {  }}

下面來實(shí)現(xiàn)一個(gè)繼承自 這個(gè)rest/ActiveController的 News 控制器:

namespace app/controllers;use app/controllers/rest/ActiveController; #剛才這個(gè)AC,我從yii/rest下面拷貝了一份出來class NewsController extends ActiveController{  public $modelClass ='app/models/News';}

定義到這里就足夠?qū)崿F(xiàn) rest/ActiveController 里面的默認(rèn)方法了
下面來覆蓋下,實(shí)現(xiàn)一些定制的方法

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 進(jìn)行大的改動(dòng),建議拷貝一份出來,不要使用原始的 yii/rest/XXXAction命名空間

我這里以要實(shí)現(xiàn)對related models進(jìn)行 CURD 操作為目標(biāo)進(jìn)行大的改動(dòng)

Action

在定制各個(gè)action之前, 先看看它們的基類 rest/Action, 主要是一個(gè) 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");    }  }}

view

view 動(dòng)作不需要改動(dòng),因?yàn)?model 有 getRelated 的自有機(jī)制

class ViewAction extend Action{  public function run($id)  {    $model = $this->findModel($id);    if($this->checkAccess) {      call_user_func($this->checkAccess, $this->id, $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;  $model->load(Yii::$app->getRequest()->getBodyParams(), '');  $model->save();  return $model;}

經(jīng)過改造后,需要滿足對關(guān)聯(lián)模型的update動(dòng)作

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;}

這里還應(yīng)該對 newsItem save 失敗 的情況進(jìn)行處理,暫且不處理。

希望本文所述對大家基于Yii框架的PHP程序設(shè)計(jì)有所幫助。


注:相關(guān)教程知識閱讀請移步到PHP教程頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表

圖片精選

主站蜘蛛池模板: 巴楚县| 大方县| 东丰县| 北辰区| 临潭县| 杭锦后旗| 大方县| 峨边| 防城港市| 白朗县| 定陶县| 崇阳县| 缙云县| 兴和县| 望谟县| 禹城市| 利川市| 青川县| 伊川县| 仙游县| 儋州市| 赫章县| 呼和浩特市| 都昌县| 教育| 来安县| 施秉县| 太保市| 黔南| 鄱阳县| 南漳县| 集安市| 湛江市| 龙海市| 宁南县| 保康县| 桓台县| 哈尔滨市| 洛扎县| 昔阳县| 怀安县|