0 フォロワー

リソース

RESTful API はすべてリソースへのアクセスと操作に関するものです。リソースはMVCパラダイムにおけるモデルとして見ることができます。

リソースをどのように表現するかについては制限はありませんが、Yii では通常、yii\base\Model またはその子クラス (例: yii\db\ActiveRecord) のオブジェクトでリソースを表現します。理由は次のとおりです。

  • yii\base\Model は、yii\base\Arrayable インターフェースを実装しています。これにより、RESTful API を介してリソースデータをどのように公開するかをカスタマイズできます。
  • yii\base\Model は、入力検証をサポートしています。これは、RESTful API でデータ入力をサポートする必要がある場合に役立ちます。
  • yii\db\ActiveRecord は、強力なDBデータアクセスと操作のサポートを提供します。これは、リソースデータがデータベースに格納されている場合に最適です。

このセクションでは、主にyii\base\Model (またはその子クラス) を拡張したリソースクラスが、RESTful API を介してどのようなデータを返すかを指定する方法について説明します。リソースクラスがyii\base\Modelを拡張しない場合、そのすべてのパブリックメンバー変数が返されます。

フィールド

リソースを RESTful API レスポンスに含める場合、リソースは文字列にシリアル化する必要があります。Yii はこのプロセスを2つのステップに分割します。まず、リソースは yii\rest\Serializer によって配列に変換されます。次に、配列はレスポンスフォーマッタによって要求された形式 (JSON、XMLなど) の文字列にシリアル化されます。リソースクラスを開発する際に主に焦点を当てるべきなのは最初のステップです。

fields() および/または extraFields() をオーバーライドすることにより、リソース内のどのデータ (フィールドと呼ばれる) を配列表現に含めるかを指定できます。これら2つのメソッドの違いは、前者が配列表現に含める必要があるフィールドのデフォルトセットを指定するのに対し、後者はエンドユーザが expand クエリパラメータを介して要求した場合に配列に含めることができる追加のフィールドを指定することです。例:

// returns all fields as declared in fields()
http:///users

// only returns "id" and "email" fields, provided they are declared in fields()
http:///users?fields=id,email

// returns all fields in fields() and field "profile" if it is in extraFields()
http:///users?expand=profile

// returns all fields in fields() and "author" from post if
// it is in extraFields() of post model
http:///comments?expand=post.author

// only returns "id" and "email" provided they are in fields() and "profile" if it is in extraFields()
http:///users?fields=id,email&expand=profile

fields() のオーバーライド

デフォルトでは、yii\base\Model::fields() はすべてのモデル属性をフィールドとして返し、yii\db\ActiveRecord::fields() はDBから取り込まれた属性のみを返します。

fields() をオーバーライドして、フィールドの追加、削除、名前変更、再定義を行うことができます。fields() の戻り値は配列である必要があります。配列のキーはフィールド名、配列の値は対応するフィールド定義であり、プロパティ/属性名または対応するフィールド値を返す匿名関数のいずれかになります。フィールド名がその定義属性名と同じ場合は、配列キーを省略できます。例えば、次のようになります。

// explicitly list every field, best used when you want to make sure the changes
// in your DB table or model attributes do not cause your field changes (to keep API backward compatibility).
public function fields()
{
    return [
        // field name is the same as the attribute name
        'id',
        // field name is "email", the corresponding attribute name is "email_address"
        'email' => 'email_address',
        // field name is "name", its value is defined by a PHP callback
        'name' => function ($model) {
            return $model->first_name . ' ' . $model->last_name;
        },
    ];
}

// filter out some fields, best used when you want to inherit the parent implementation
// and exclude some sensitive fields.
public function fields()
{
    $fields = parent::fields();

    // remove fields that contain sensitive information
    unset($fields['auth_key'], $fields['password_hash'], $fields['password_reset_token']);

    return $fields;
}

警告: デフォルトでは、モデルのすべての属性がAPI結果に含まれるため、データに機密情報が含まれていないか確認する必要があります。そのような情報がある場合は、fields() をオーバーライドしてそれらをフィルタリングする必要があります。上記の例では、auth_keypassword_hash、および password_reset_token をフィルタリングすることを選択しています。

extraFields() のオーバーライド

デフォルトでは、yii\base\Model::extraFields() は空の配列を返し、yii\db\ActiveRecord::extraFields() はDBから取得されたリレーションの名前を返します。

extraFields() の戻り値の形式は、fields() と同じです。通常、extraFields() は主に値がオブジェクトであるフィールドを指定するために使用されます。例えば、次のフィールド宣言の場合、

public function fields()
{
    return ['id', 'email'];
}

public function extraFields()
{
    return ['profile'];
}

https:///users?fields=id,email&expand=profile のリクエストは、次のJSONデータを返す可能性があります。

[
    {
        "id": 100,
        "email": "100@example.com",
        "profile": {
            "id": 100,
            "age": 30,
        }
    },
    ...
]

HATEOAS(Hypermedia as the Engine of Application Stateの略)は、RESTful APIが、返されたリソースでサポートされるアクションを発見できるようにする情報を返すことを推奨します。HATEOASの鍵は、APIがリソースデータを提供する際に、関係情報を含むハイパーリンクのセットを返すことです。

リソースクラスは、yii\web\Linkable インターフェースを実装することでHATEOASをサポートできます。このインターフェースには、getLinks() という単一のメソッドが含まれており、リンクのリストを返す必要があります。通常、リソースオブジェクト自体へのURLを表す self リンクを少なくとも返す必要があります。例えば、次のようになります。

use yii\base\Model;
use yii\web\Link; // represents a link object as defined in JSON Hypermedia API Language.
use yii\web\Linkable;
use yii\helpers\Url;

class UserResource extends Model implements Linkable
{
    public $id;
    public $email;

    //...

    public function fields()
    {
        return ['id', 'email'];
    }

    public function extraFields()
    {
        return ['profile'];
    }

    public function getLinks()
    {
        return [
            Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
            'edit' => Url::to(['user/view', 'id' => $this->id], true),
            'profile' => Url::to(['user/profile/view', 'id' => $this->id], true),
            'index' => Url::to(['users'], true),
        ];
    }
}

UserResource オブジェクトがレスポンスで返されると、ユーザーに関連するリンクを表す _links 要素が含まれます。例えば、次のようになります。

{
    "id": 100,
    "email": "user@example.com",
    // ...
    "_links" => {
        "self": {
            "href": "https://example.com/users/100"
        },
        "edit": {
            "href": "https://example.com/users/100"
        },
        "profile": {
            "href": "https://example.com/users/profile/100"
        },
        "index": {
            "href": "https://example.com/users"
        }
    }
}

コレクション

リソースオブジェクトはコレクションにグループ化できます。各コレクションには、同じタイプのリソースオブジェクトのリストが含まれています。

コレクションは配列として表現できますが、データプロバイダとして表現する方が通常は望ましいです。これは、データプロバイダがリソースのソートとページネーションをサポートしており、これはコレクションを返すRESTful APIによく必要とされる機能であるためです。例えば、次のアクションは、投稿リソースに関するデータプロバイダを返します。

namespace app\controllers;

use yii\rest\Controller;
use yii\data\ActiveDataProvider;
use app\models\Post;

class PostController extends Controller
{
    public function actionIndex()
    {
        return new ActiveDataProvider([
            'query' => Post::find(),
        ]);
    }
}

データプロバイダがRESTful APIレスポンスで送信される場合、yii\rest\Serializer は、リソースの現在のページを取り出し、リソースオブジェクトの配列としてシリアライズします。さらに、yii\rest\Serializer は、次のHTTPヘッダーによってページネーション情報も含まれます。

  • X-Pagination-Total-Count: リソースの合計数;
  • X-Pagination-Page-Count: ページ数;
  • X-Pagination-Current-Page: 現在のページ (1ベース);
  • X-Pagination-Per-Page: 各ページの リソース数;
  • Link: クライアントがリソースをページごとに移動できるようにするナビゲーションリンクのセット。

REST APIのコレクションはデータプロバイダであるため、ページネーションやソートなど、すべてのデータプロバイダ機能が共有されます。

例は、クイックスタートセクションにあります。

タイプミスを見つけたり、このページの改善が必要だと感じましたか?
githubで編集する !