1. 程式人生 > >【RESTful】Yii2實現RESTful架構配置最佳實踐

【RESTful】Yii2實現RESTful架構配置最佳實踐

Yii2實現RESTful架構配置最佳實踐

為什麼要用RESTful API

在伺服器端,應用程式狀態和功能可以分為各種資源。資源是一個有趣的概念實體,它向客戶端公開。資源的例子有:應用程式物件、資料庫記錄、演算法等等。每個資源都使用 URI (Universal Resource Identifier) 得到一個唯一的地址。所有資源都共享統一的介面,以便在客戶端和伺服器之間傳輸狀態。使用的是標準的 HTTP 方法,比如 GET、PUT、POST 和 DELETE。Hypermedia 是應用程式狀態的引擎,資源表示通過超連結互聯。

無狀態,分層,可擴充套件

本文為原創部落格,被收錄在我自己的GitHub專案中

點我檢視專案檔案

基於Yii2的RESTful API 的實現

不用自帶的REST實現方式

首先,Yii2自帶了實現RESTful api的方式,但是,官方的例子過於簡單,把一個資源限定成了資料庫中的一個表,這顯然是和REST中定義的資源不相符的,並且實際的業務需求過於複雜,不能通過一個表進行資料的操作。

所以,我們採用了另一種方式,通過使用Yii2的不同元件,完成RESTful API的構建

路由

REST要求定義資源,採用不同HTTP方式進行訪問。

這裡用到了框架內部的路由

在專案的配置檔案/config/web.php,中,對不同資源進行路由設定,從而達到同一個URL用不同的訪問方式來處理不同業務的目的。

        //url配置對應規則
        'urlManager' => [
            'enablePrettyUrl' => true,
            'showScriptName' => false,
            'rules' => [
                //配置規則,實現RESTful的方式
                'POST accounts'=>'account/login', // 登入
                'GET accounts'=>'account/get-avatar'
, //獲取頭像 "GET accounts/status"=>'account/status', //查詢登入狀態 //獲取使用者組資訊 "GET groups"=>"account/profile", //使用者申請加入使用者組的介面 "GET users/ask"=>"user/apply", //申請列表 "PUT users/<uid:\d+>"=>"user/pass", //通過 "PATCH users/<uid:\d+>"=>"user/nopass", //不通過 "GET users"=>"user/list", //通過的使用者列表 "DELETE users/<uid:\d+>"=>"user/remove", //移除現有的使用者 "GET users/<uid:\d+>"=>"user/info", //網紅的具體資訊 "GET users/serach"=>"user/serach", //搜尋當前使用者的使用者 //訊息中心相關 "GET notices"=>"notice/list", //訊息列表 "PUT notices/<nid:\d+>"=>"notice/mark", //訊息標記為已讀 "GET notices/status"=>"notice/status", //獲取訊息的概要 ],

這部分的設計,參考官方文件對於RESTful實現的部分

  • GET /users: 逐頁列出所有使用者
  • HEAD /users: 顯示使用者列表的概要資訊
  • POST /users: 建立一個新使用者
  • GET /users/123: 返回使用者 123 的詳細資訊
  • HEAD /users/123: 顯示使用者 123 的概述資訊
  • PATCH /users/123 and PUT /users/123: 更新使用者123
  • DELETE /users/123: 刪除使用者123
  • OPTIONS /users: 顯示關於末端 /users 支援的動詞
  • OPTIONS /users/123: 顯示有關末端 /users/123 支援的動詞

接收資料

我們需要獲取客戶端傳遞過來的GET,POST,Header的資料,框架自帶了Yii::$app->request,可以直接得到客戶端傳過來的資料。

參考\yii\web\Request|\yii\console\Request $request The request component. This property is read-only.

處理資料

這部分和一般的專案一樣,都用/models中的資料表對應的Model檔案,繼承了\yii\db\ActiveRecord的類,實現對資料表的CURD操作。

響應資料

我們在處理資料之後,需要返回給客戶端對應的資料,在REST的設計規則裡是這樣處理的

  • Body只返回主要的資料,比如使用者列表,使用者的詳細資料
  • Header返回其他的資訊,包括頁碼資訊,身份校驗資訊
  • 完全的使用HTTP狀態碼作為資源被請求狀態的返回,比如404,403

HTTP狀態碼的說明如下

Code HTTP Operation Body Contents Description
200 GET,PUT 資源 操作成功
201 POST 資源,元資料 物件建立成功
202 POST,PUT,DELETE,PATCH N/A 請求已經被接受
204 DELETE,PUT,PATCH N/A 操作已經執行成功,但是沒有返回資料
301 GET link 資源已被移除
303 GET link 重定向
304 GET N/A 資源沒有被修改
400 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 引數列表錯誤(缺少,格式不匹配)
401 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 未授權
403 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 訪問受限,授權過期
404 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 資源,服務未找到
405 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 不允許的http方法
409 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 資源衝突,或者資源被鎖定
415 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 不支援的資料(媒體)型別
429 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 請求過多被限制
500 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 系統內部錯誤
501 GET,PSOT,PUT,DELETE,PATCH 錯誤提示(訊息) 介面未實現

格式化資料,我們的返回資料的格式為JSON

$response= Yii::$app->response;
$response->format = \yii\web\Response::FORMAT_JSON; //返回json

錯誤處理

通過不同的錯誤碼,返回不同的HTTP狀態碼。

由於的非常頻繁的呼叫,所以對資料進行了封裝。

錯誤處理類Error.php


/**
 * 錯誤處理類
 * 
 * ------------------------------------
 * 
 * 錯誤處理擴充套件 seaslog
 * 
 * http://www.oschina.net/news/50333/seaslog-0-21
 * 
 * http://neeke.github.io/SeasLog/
 *
 * ------------------------------------
 * 
 * @author Calvin 
 * @version 1.0
 * @copyright (c) 2016,
 */

namespace app\components\error;

use Yii;

class Error {

    /**
     * 公共的錯誤返回處理,通過傳入引數,返回對應的錯誤程式碼,這裡也定義了錯誤返回的格式,以及對日誌的記錄
     *
     * @param $error_code
     * @return array
     */
    public static function errorJson($error_code) {
        $requests = Yii::$app->request; //返回值
        $post = json_encode($requests->post());
        $get = json_encode($requests->get());
        $headers = json_encode($requests->getHeaders()->toArray());

        //帶入記錄錯誤程式碼的檔案
        $error_file = require_once \Yii::$app->basePath . "/components/error/ErrorCode.php";
        //獲取http狀態碼,以及文字說明
        $error_info = $error_file["$error_code"];


        $http_code = $error_info['http_code'];
        $error_text = $error_info['remark'];

        $error_body = [ //設定返回的格式
            'request' => $requests->getUrl(),
            'method'=>$requests->getMethod(),
            'error_code' => $error_code,
            'error' =>$error_text,
        ];

        $response = Yii::$app->response;
        $response->statusCode=$http_code;
        $response->format = \yii\web\Response::FORMAT_JSON;
        $headers = Yii::$app->response->headers;
        $headers->add('X-Halo-Result', 0);
//        $response->data = $error_body;


//        $userIP = $requests->userIP;
        //寫入日誌
//        \SeasLog::error('error === {error} && error_text === {error_text}  && userIP === {userIP} && post === {post}  && get === {get} && header === {header} ', [
//            '{error}' => $error,
//            '{error_text}' => $error_file["$error"],
//            '{post}' => $post,
//            '{get}' => $get,
//            '{userIP}' => $userIP,
//            '{header}' => $headers,
//                ], $request);
//        $appLog = \Alibaba::AppLog();
//        $appLog->debug("debug-log-emssage");
//        $appLog->info("info-log-emssage");
//        $appLog->warn("warn-log-emssage");
//        $appLog->error("error-log-emssage");

        return $error_body;
    }

}

錯誤程式碼檔案ErrorCode.php

/**
 * 增加對不同型別的HTTP狀態碼的返回
 *
 * 錯誤碼,HTTP狀態碼,返回值
 */
return [
    '1001'=>[
        'http_code'=>403,
        'remark'=>"Token驗證失敗",
    ],
    '1002'=>[
        'http_code'=>400,
        'remark'=>"引數錯誤",
    ],
    '1003'=>[
        'http_code'=>400,
        'remark'=>"引數不全",
    ],
    '2001'=>[
        'http_code'=>404,
        'remark'=>"使用者不存在",
    ],

];

呼叫錯誤資料返回

return Error::errorJson(1002);

文件

有句話說得好,程式設計師不願意寫文件,但是看到沒有文件的專案又會抓狂。。。。

概括結構

一個合格的API文件應該包含下面幾項

  • 概括說明
  • 加密協議
  • 資料型別
  • 錯誤處理
  • 介面文件
  • 參考資料

介面文件

介面文件告訴客戶端,呼叫什麼資料,怎麼掉,異常了咋辦。。。

  • 簡單說明
  • 訪問地址
  • 請求方式
  • 返回結果
  • 返回結果欄位說明
  • 錯誤程式碼
  • 更新記錄

總結

RESTful API的好處在於更簡潔的規範了資料請求的方式,通過資源來設計資料介面,方便客戶端的呼叫,減少溝通成本。

不過協議畢竟只是個建議,我們可以根據自己專案的實際情況,有選擇的滿足協議的需求,更好的為自己的專案服務。

:)

參考資料