5 追隨者

控制器

在建立資源類別並指定資源資料應如何格式化之後,接下來要做的是建立控制器動作,以透過 RESTful API 將資源公開給終端使用者。

Yii 提供了兩個基礎控制器類別,以簡化您建立 RESTful 動作的工作:yii\rest\Controlleryii\rest\ActiveController。這兩個控制器之間的區別在於,後者提供了一組預設動作,這些動作專門設計用於處理以 Active Record 表示的資源。因此,如果您正在使用 Active Record,並且對提供的內建動作感到滿意,您可以考慮從 yii\rest\ActiveController 擴展您的控制器類別,這將使您能夠以最少的程式碼建立強大的 RESTful API。

yii\rest\Controlleryii\rest\ActiveController 都提供以下功能,其中一些功能將在接下來的幾個章節中詳細描述

yii\rest\ActiveController 此外還提供以下功能

  • 一組常用的動作:indexviewcreateupdatedeleteoptions
  • 關於請求的動作和資源的使用者授權。

建立控制器類別

在建立新的控制器類別時,命名控制器類別的慣例是使用資源的類型名稱並使用單數形式。例如,為了提供使用者資訊,控制器可以命名為 UserController

建立新的動作與為 Web 應用程式建立動作類似。唯一的區別在於,對於 RESTful 動作,您直接傳回資料,而不是透過呼叫 render() 方法使用視圖呈現結果。序列化器回應物件將處理從原始資料到請求格式的轉換。例如,

public function actionView($id)
{
    return User::findOne($id);
}

過濾器

yii\rest\Controller 提供的多數 RESTful API 功能都是以過濾器的形式實作的。特別是,以下過濾器將按照它們列出的順序執行

這些命名的過濾器在 behaviors() 方法中宣告。您可以覆寫此方法來配置個別過濾器、停用其中一些過濾器或新增您自己的過濾器。例如,如果您只想使用 HTTP 基本身份驗證,您可以編寫以下程式碼

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::class,
    ];
    return $behaviors;
}

CORS

跨來源資源共享 過濾器新增到控制器比新增上述其他過濾器要複雜一些,因為 CORS 過濾器必須在身份驗證方法之前應用,因此與其他過濾器相比,需要稍微不同的方法。此外,對於 CORS 預檢請求 必須停用身份驗證,以便瀏覽器可以安全地預先判斷是否可以發出請求,而無需傳送身份驗證憑證。以下顯示了將 yii\filters\Cors 過濾器新增到從 yii\rest\ActiveController 擴展的現有控制器所需的程式碼

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();

    // remove authentication filter
    $auth = $behaviors['authenticator'];
    unset($behaviors['authenticator']);
    
    // add CORS filter
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::class,
    ];
    
    // re-add authentication filter
    $behaviors['authenticator'] = $auth;
    // avoid authentication on CORS-pre-flight requests (HTTP OPTIONS method)
    $behaviors['authenticator']['except'] = ['options'];

    return $behaviors;
}

擴展 ActiveController

如果您的控制器類別從 yii\rest\ActiveController 擴展,您應該將其 modelClass 屬性設定為您計劃透過此控制器提供的資源類別的名稱。該類別必須從 yii\db\ActiveRecord 擴展。

自訂動作

預設情況下,yii\rest\ActiveController 提供以下動作

  • index:逐頁列出資源;
  • view:傳回指定資源的詳細資訊;
  • create:建立新資源;
  • update:更新現有資源;
  • delete:刪除指定的資源;
  • options:傳回支援的 HTTP 方法。

所有這些動作都透過 actions() 方法宣告。您可以配置這些動作或透過覆寫 actions() 方法來停用其中一些動作,如下所示,

public function actions()
{
    $actions = parent::actions();

    // disable the "delete" and "create" actions
    unset($actions['delete'], $actions['create']);

    // customize the data provider preparation with the "prepareDataProvider()" method
    $actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];

    return $actions;
}

public function prepareDataProvider()
{
    // prepare and return a data provider for the "index" action
}

請參閱個別動作類別的類別參考,以了解可用的配置選項。

執行存取檢查

當透過 RESTful API 公開資源時,您通常需要檢查目前使用者是否具有存取和操作請求資源的權限。使用 yii\rest\ActiveController,可以透過覆寫 checkAccess() 方法來完成,如下所示,

/**
 * Checks the privilege of the current user.
 *
 * This method should be overridden to check whether the current user has the privilege
 * to run the specified action against the specified data model.
 * If the user does not have access, a [[ForbiddenHttpException]] should be thrown.
 *
 * @param string $action the ID of the action to be executed
 * @param \yii\base\Model $model the model to be accessed. If `null`, it means no specific model is being accessed.
 * @param array $params additional parameters
 * @throws ForbiddenHttpException if the user does not have access
 */
public function checkAccess($action, $model = null, $params = [])
{
    // check if the user can access $action and $model
    // throw ForbiddenHttpException if access should be denied
    if ($action === 'update' || $action === 'delete') {
        if ($model->author_id !== \Yii::$app->user->id)
            throw new \yii\web\ForbiddenHttpException(sprintf('You can only %s articles that you\'ve created.', $action));
    }
}

checkAccess() 方法將由 yii\rest\ActiveController 的預設動作呼叫。如果您建立新的動作並且也想執行存取檢查,您應該在新動作中明確呼叫此方法。

提示: 您可以使用基於角色的存取控制 (RBAC) 組件來實作 checkAccess()

發現錯字或您認為此頁面需要改進?
在 github 上編輯 !