您好,登錄后才能下訂單哦!
這篇文章將為大家詳細(xì)講解有關(guān)Yii2中Restful API的示例分析,小編覺(jué)得挺實(shí)用的,因此分享給大家做個(gè)參考,希望大家閱讀完這篇文章后可以有所收獲。
具體如下:
Yii2 有個(gè)很重要的特性是對(duì) Restful API的默認(rèn)支持, 通過(guò)短短的幾個(gè)配置就可以實(shí)現(xiàn)簡(jiǎn)單的對(duì)現(xiàn)有Model的RESTful API
這里通過(guò)分析rest部分源碼,簡(jiǎn)單剖析下yii2 實(shí)現(xiàn) restful 的原理,并通過(guò)一些定制實(shí)現(xiàn) 對(duì) 關(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 控制器類(lèi)的基類(lèi)
它在一個(gè)API請(qǐng)求的控制周期中一次實(shí)現(xiàn)了下面的步驟 1~5:
① 解析響應(yīng)的內(nèi)容格式
② 校驗(yàn)請(qǐng)求方法
③ 檢驗(yàn)用戶(hù)權(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 rateLimiter afterAction 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 的類(lèi)名由 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
可以通過(guò)覆蓋 actions() 并且 unsetting 響應(yīng)的 action 來(lái)禁用這些默認(rèn)的動(dòng)作。
要增加一個(gè)新的動(dòng)作, 覆蓋 actions() 向其末尾增加一個(gè)新的 action class 或者 是一個(gè)新的 action method
注意一點(diǎn),確保你同時(shí)也覆蓋了 verbs() 方法來(lái)聲明這個(gè)新的動(dòng)作支持那些HTTP Method
也需要覆蓋checkAccess() 來(lái)檢查當(dāng)前用戶(hù)是否有權(quán)限來(lái)執(zhí)行響應(yīng)的某個(gè)動(dòng)作。
根據(jù)上面的說(shuō)明再寫(xiě)一遍 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 = []) { } }
下面來(lái)實(shí)現(xiàn)一個(gè)繼承自 這個(gè)rest\ActiveController的 News 控制器:
namespace app\controllers; use app\controllers\rest\ActiveController; #剛才這個(gè)AC,我從yii/rest下面拷貝了一份出來(lái) class NewsController extends ActiveController { public $modelClass ='app\models\News'; }
定義到這里就足夠?qū)崿F(xiàn) rest\ActiveController 里面的默認(rèn)方法了
下面來(lái)覆蓋下,實(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
如果要對(duì) Actions 進(jìn)行大的改動(dòng),建議拷貝一份出來(lái),不要使用原始的 yii\rest\XXXAction命名空間
我這里以要實(shí)現(xiàn)對(duì)related models進(jìn)行 CURD 操作為目標(biāo)進(jìn)行大的改動(dòng)
Action
在定制各個(gè)action之前, 先看看它們的基類(lèi) 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ò)改造后,需要滿(mǎn)足對(duì)關(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)該對(duì) newsItem save 失敗 的情況進(jìn)行處理,暫且不處理。
關(guān)于“Yii2中Restful API的示例分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,使各位可以學(xué)到更多知識(shí),如果覺(jué)得文章不錯(cuò),請(qǐng)把它分享出去讓更多的人看到。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。