成人精品一区二区三区中文字幕-成人精品一区二区三区-成人精品一级毛片-成人精品亚洲-日本在线视频一区二区-日本在线视频免费

導航首頁 ? 技術教程 ? Yii2中Restful API原理實例分析
全站頭部文字 我要出現在這里
Yii2中Restful API原理實例分析 730 2024-01-29   

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

Yii2 有個很重要的特性是對 Restful API的默認支持, 通過短短的幾個配置就可以實現簡單的對現有Model的RESTful API

這里通過分析rest部分源碼,簡單剖析下yii2 實現 restful 的原理,并通過一些定制實現 對 關聯模型的RESTful api 操作。

~ 代表 extends from 的關系

| | rest/
| | |-Action.php ~ `yiibaseAction`
| | |-Controller.php ~ `yiiwebController`
| | | |-ActiveController.php ~ `restController`
| | |-Serializer.php ~ `yiibaseComponent`
| | |-UrlRule.php ~ `yiiwebCompositeUrlRule`
| | |-CreateAction.php ~ `restAction`
| | |-DeleteAction.php ~ `restAction`
| | |-IndexAction.php ~ `restAction`
| | |-OptionsAction.php ~ `restAction`
| | |-UpdateAction.php ~ `restAction`
| | |-ViewAction.php ~ `restAction`

1. rest/Controller ~ yiiwebController

Controller是 RESTful API 控制器類的基類

它在一個API請求的控制周期中一次實現了下面的步驟 1~5:

① 解析響應的內容格式
② 校驗請求方法
③ 檢驗用戶權限
④ 限制速度
⑤ 格式化響應數據

use yiifiltersauthCompositeAuth;
use yiifiltersContentNegotiator;
use yiifiltersRateLimiter;
use yiiwebResponse;
use yiifiltersVerbFilter;
/**
 * 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 [[yiifiltersauthAuthInterface]]);
 * 4. Rate limiting (see [[RateLimiter]]);
 * 5. Formatting response data (see [[serializeData()]])
behaviors
  contentNegotiator
  verbFilter
  authenticator
  rateLimiter
afterAction
  serializeData Yii::createObject($this->serializer)->serialize($data)
verbs []
*/
class Controller extends yiiwebController
{
  public $serializer = 'yiirestSerializer';
  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 實現了一系列的和 ActiveRecord 互通數據的RESTful方法

ActiveRecord 的類名由 modelClass 變量指明, yiidbActiveRecordInterface ???

默認的, 支持下面的方法:

* - `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() 來檢查當前用戶是否有權限來執行響應的某個動作。

根據上面的說明再寫一遍 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' => 'appcontrollersrestIndexAction',
        '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 = [])
  {
  }
}

下面來實現一個繼承自 這個restActiveController的 News 控制器:

namespace appcontrollers;
use appcontrollersrestActiveController; #剛才這個AC,我從yii/rest下面拷貝了一份出來
class NewsController extends ActiveController
{
  public $modelClass ='appmodelsNews';
}

定義到這里就足夠實現 restActiveController 里面的默認方法了
下面來覆蓋下,實現一些定制的方法

class NewsController extends ActiveController
{
  public $modelClass = 'appmodelsNews';
  #定制serializer
  #public $serializer = 'yiirestSerializer';
  public $serializer = [
    'class' => 'appcontrollersrestSerializer',
    '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 進行大的改動,建議拷貝一份出來,不要使用原始的 yiirestXXXAction命名空間

我這里以要實現對related models進行 CURD 操作為目標進行大的改動

Action

在定制各個action之前, 先看看它們的基類 restAction, 主要是一個 findModel的方法

class Action extend yiibaseAction
{
  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 動作不需要改動,因為 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);
    }
  }
}

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

經過改造后,需要滿足對關聯模型的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程序設計有所幫助。



主站蜘蛛池模板: e-dog| 星河长明免费观看电视剧| 欧美一级在线视频| 郑楚一| 谍影 电视剧| 伪装者 豆瓣| 金枝欲孽在线观看免费完整版| 二年级最佳家长评语| 绷带怪人| 轨迹地图| 去2| 推普周主题班会活动记录| cad| 黄电影在线观看| 女人战争之肮脏的交易| 爱上特种兵电视剧免费观看完整版 | 宋小莹| 那个不为人知的故事电视剧| 风间电影正版免费观看| 女孩们的周末| 姨妈来之前的征兆有哪些| 汤图片大全高清图片| 杨玉环一级片| 黄视频在线网站| 视频一级片| 雪中悍刀行第一季演员表| 双妻艳| 红剪花| 浙江卫视节目在线观看直播| 孤芳岚影| 全国急招压路机师傅| 薛佳凝个人资料图片简介| 豆包简历个人资料| lanarhoades在线av| 十个世界尽头| 喜欢小红帽的原因怎么写| 那些女人电视剧免费观看全集剧情| 大地资源高清播放在线观看| 发狂的现代史在线观看| dj歌曲串烧中文大全| 吉泽明步番号|

!!!站長長期在線接!!!

網站、小程序:定制開發/二次開發/仿制開發等

各種疑難雜癥解決/定制接口/定制采集等

站長微信:lxwl520520

站長QQ:1737366103