Yii2開發筆記系列二:使用module做api版本化

zhuzixian520發表於2022-01-24

建立目錄及檔案

在你所在的專案 api 目錄下,配置好開發的域名,並進入 gii 頁面(例如:http://yourdomain/gii),建立 module

Yii2開發筆記系列二:使用module做api版本化

當多版本的時候,可以建立 v2,以此類推
Yii2開發筆記系列二:使用module做api版本化
預設建立了一個 DefaultController

配置

開啟 /api/config/main.php

return [
    'modules' => [
        'v1' => [
            'class' => 'api\modules\v1\V1Module',
        ],
    ],
]

訪問預設介面

您的開發環境介面訪問地址,大概如下:
yourdomain/va/default/index
訪問成功,即可

基類建立

在 /api/controllers 目錄下,新建一個 BaseRestController.php,大概內容如下

<?php

namespace api\controllers;

use Yii;
use yii\base\Event;
use yii\filters\ContentNegotiator;
use yii\filters\Cors;
use yii\filters\RateLimiter;
use yii\rest\Controller;
use yii\web\MethodNotAllowedHttpException;
use yii\web\Response;

class BaseRestController extends Controller
{
    const CONTENT_TYPE = [
        'application/json',
        'application/json;charset=UTF-8',
        'application/json;charset=utf-8',
    ];

    public array $payload = [];

    /**
     * @inheritdoc
     */
    public function init()
    {
        parent::init();

        //Yii::$app->request->enableCsrfValidation = true;
        Yii::$app->user->enableSession = false;
        Yii::$app->user->enableAutoLogin = false;

        //給介面響應結果繫結beforeSend事件
        Yii::$app->getResponse()->on(Response::EVENT_BEFORE_SEND, [$this, 'beforeSend']);
    }

    /**
     * @inheritdoc
     */
    public function behaviors()
    {
        $behaviors = parent::behaviors();
        unset($behaviors['authenticator']);

        //跨域
        $behaviors['corsFilter'] = [
            'class' => Cors::class,
            'cors' => [
                // restrict access to
                'Origin' => ['*'],
                // Allow methods
                'Access-Control-Request-Method' => ['POST', 'GET', 'OPTIONS', 'HEAD'],
                // Allow only headers 'X-Wsse'
                'Access-Control-Request-Headers' => ['*'],
                // Allow credentials (cookies, authorization headers, etc.) to be exposed to the browser
                'Access-Control-Allow-Credentials' => false,
                // Allow OPTIONS caching
                'Access-Control-Max-Age' => 3600,
                // Allow the X-Pagination-Current-Page header to be exposed to the browser.
                //'Access-Control-Expose-Headers' => ['x-token',],
            ],
        ];

        $behaviors['contentNegotiator'] = [
            'class' => ContentNegotiator::class,
            'formats' => [
                'application/json' => Response::FORMAT_JSON
            ]
        ];

        /*$behaviors['authenticator'] = [
            //'class' => HttpBasicAuth::class
            //'class' => HttpHeaderAuth::class
            //'class' => HttpBearerAuth::class
            //'class' => QueryParamAuth::class
            //'class' => CompositeAuth::class
            //'optional' => [],
        ];*/

        //介面速率限制
        /*$behaviors['rateLimiter'] = [
            'class' => RateLimiter::className(),
            'enableRateLimitHeaders' => false,
            'errorMessage' => '請求過於頻繁,請稍後重試',
        ];*/

        return $behaviors;
    }

    /**
     * @inheritdoc
     * @param \yii\base\Action $action
     * @return bool
     * @throws MethodNotAllowedHttpException
     * @throws \yii\web\BadRequestHttpException
     */
    public function beforeAction($action): bool
    {
        if (!parent::beforeAction($action)) {
            return false;
        }

        /*$isPost = Yii::$app->request->isPost;
        if (!$isPost) {
            throw new MethodNotAllowedHttpException();
        }*/

        //獲取引數
        $contentType = Yii::$app->request->contentType;
        if (in_array($contentType, self::CONTENT_TYPE))
            $this->payload = (array)json_decode(file_get_contents('php://input'), true);

        return true;
    }

    /**
     * @param Event $event
     */
    public function beforeSend(Event $event)
    {
        /* @var $response yii\web\Response */
        $response = $event->sender;

        //針對Yii2框架404預設返回的是html頁面,rest薛強沒處理
        if ($response->statusCode === 404){
            $response->format = Response::FORMAT_JSON;
            $response->data = [
                'name' => $response->statusText,
                'message' => '請求不存在',
                'code' => 0,
                'status' => 404,
            ];
        }
    }
}

可以講次檔案作為控制器的基類

格式化介面返回

介面成功返回

[
    'message' => 'success',
    'code' => 0,
    'data' => [],
    'status' => 200, //http狀態碼
]
介面失敗返回,有兩種,一種是請求成功,但是有一些欄位驗證的錯誤
[
    'message' => 'failed',
    'code' => 1,
]
還有http錯誤,此時會有status欄位返回,401,403,404,405等,
[
    'message' => 'failed',
    'code' => 1,
    'stutus' => 401,
]

具體風格,可以自己設定,本文按照 Yii2 自帶的欄位而寫的

本作品採用《CC 協議》,轉載必須註明作者和本文連結
Trevor(zhuzixian520@126.com)

相關文章