コントローラ

リソース・クラスを作成して、リソース・データをどのようにフォーマットすべきかを指定したら、 次は、RESTful API を通じてエンド・ユーザにリソースを公開するコントローラ・アクションを作成します。

Yii は、RESTful アクションを作成する仕事を簡単にするための二つの基底コントローラ・クラスを提供しています。 すなわち、yii\rest\Controlleryii\rest\ActiveController です。 二つのコントローラの違いは、後者は アクティブ・レコード として表現されるリソースの扱いに特化した一連のアクションをデフォルトで提供する、という点にあります。 従って、あなたが アクティブ・レコード を使っていて、提供される組み込みのアクションに満足できるのであれば、 コントローラ・クラスを yii\rest\ActiveController から拡張することを検討すると良いでしょう。 そうすれば、最小限のコードで強力な RESTful API を作成することが出来ます。

yii\rest\Controlleryii\rest\ActiveController は、ともに、下記の機能を提供します。 これらのいくつかについては、後続のセクションで詳細に説明します。

yii\rest\ActiveController は次の機能を追加で提供します。

  • 普通は必要とされる一連のアクション: indexviewcreateupdatedeleteoptions
  • リクエストされたアクションとリソースに対するユーザへの権限付与

コントローラ・クラスを作成する

新しいコントローラ・クラスを作成する場合、コントローラ・クラスの命名規約は、 リソースの型の名前を単数形で使う、というものです。 例えば、ユーザの情報を提供するコントローラは UserController と名付けることが出来ます。

新しいアクションを作成する仕方はウェブ・アプリケーションの場合とほぼ同じです。 唯一の違いは、render() メソッドを呼んでビューを使って結果を表示する代りに、RESTful アクションの場合はデータを直接に返す、という点です。 シリアライザレスポンス・オブジェクト が、 元のデータからリクエストされた形式への変換を処理します。 例えば、

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::className(),
    ];
    return $behaviors;
}

CORS

コントローラに CORS (クロス・オリジン・リソース共有) フィルタを追加するのは、上記の他のフィルタを追加するのより、若干複雑になります。 と言うのは、CORS フィルタは認証メソッドより前に適用されなければならないため、他のフィルタとは少し異なるアプローチが必要だからです。 また、ブラウザが認証クレデンシャルを送信する必要なく、リクエストが出来るかどうかを前もって安全に判断できるように、 CORS プリフライト・リクエスト の認証を無効にする必要もあります。 下記のコードは、yii\rest\ActiveController を拡張した既存のコントローラに yii\filters\Cors フィルタを追加するのに必要なコードを示しています。

use yii\filters\auth\HttpBasicAuth;

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

    // 認証フィルタを削除する
    $auth = $behaviors['authenticator'];
    unset($behaviors['authenticator']);
    
    // CORS フィルタを追加する
    $behaviors['corsFilter'] = [
        'class' => \yii\filters\Cors::className(),
    ];
    
    // 認証フィルタを再度追加する
    $behaviors['authenticator'] = $auth;
    // CORS プリフライト・リクエスト (HTTP OPTIONS メソッド) の認証を回避する
    $behaviors['authenticator']['except'] = ['options'];

    return $behaviors;
}

ActiveController を拡張する

コントローラを yii\rest\ActiveController から拡張する場合は、このコントローラを通じて提供しようとしているリソース・クラスの名前を modelClass プロパティにセットしなければなりません。 リソース・クラスは yii\db\ActiveRecord から拡張しなければなりません。

アクションをカスタマイズする

デフォルトでは、yii\rest\ActiveController は次のアクションを提供します。

  • options: サポートされている HTTP メソッドを返す。

これらのアクションは全て actions() メソッドによって宣言されます。 actions() メソッドをオーバーライドすることによって、これらのアクションを構成したり、そのいくつかを無効化したりすることが出来ます。例えば、

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

    // "delete" と "create" のアクションを無効にする
    unset($actions['delete'], $actions['create']);

    // データ・プロバイダの準備を "prepareDataProvider()" メソッドでカスタマイズする
    $actions['index']['prepareDataProvider'] = [$this, 'prepareDataProvider'];

    return $actions;
}

public function prepareDataProvider()
{
    // "index" アクションのためにデータ・プロバイダを準備して返す
}

どういう構成オプションが利用できるかを学ぶためには、個々のアクション・クラスのリファレンスを参照してください。

アクセス・チェックを実行する

RESTful API によってリソースを公開するときには、たいてい、 現在のユーザがリクエストしているリソースにアクセスしたり操作したりする許可を持っているか否かをチェックする必要があります。 これは、yii\rest\ActiveController を使う場合は、checkAccess() メソッドを次のようにオーバーライドすることによって出来ます。

/**
 * 現在のユーザの特権をチェックする。
 *
 * 現在のユーザが指定されたデータ・モデルに対して指定されたアクションを実行する特権を
 * 有するか否かをチェックするためには、このメソッドをオーバーライドしなければなりません。
 * ユーザが権限をもたない場合は、[[ForbiddenHttpException]] が投げられなければなりません。
 *
 * @param string $action 実行されるアクションの ID。
 * @param \yii\base\Model $model アクセスされるモデル。null の場合は、アクセスされる特定のモデルが無いことを意味する。
 * @param array $params 追加のパラメータ
 * @throws ForbiddenHttpException ユーザが権限をもたない場合
 */
public function checkAccess($action, $model = null, $params = [])
{
    // ユーザが $action と $model に対する権限を持つかどうかをチェック
    // アクセスを拒否すべきときは ForbiddenHttpException を投げる
    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 のデフォルトのアクションから呼ばれます。 新しいアクションを作成して、それに対してもアクセス・チェックをしたい場合は、新しいアクションの中からこのメソッドを明示的に呼び出さなければなりません。

Tip: ロール・ベース・アクセス制御 (RBAC) コンポーネント を使って checkAccess() を実装することも可能です。