RESTful API 的核心在於存取和操作資源。您可以將資源視為 MVC 範例中的模型。
雖然如何表示資源沒有限制,但在 Yii 中,您通常會使用 yii\base\Model 或其子類別(例如 yii\db\ActiveRecord)的物件來表示資源,原因如下:
在本節中,我們將主要描述如何從 yii\base\Model(或其子類別)擴充的資源類別,可以指定哪些資料可以透過 RESTful API 回傳。如果資源類別不是從 yii\base\Model 擴充,則將會回傳其所有公開成員變數。
當在 RESTful API 回應中包含資源時,需要將資源序列化為字串。Yii 將此過程分為兩個步驟。首先,資源由 yii\rest\Serializer 轉換為陣列。其次,陣列由回應格式器序列化為請求格式(例如 JSON、XML)的字串。第一步是您在開發資源類別時應主要關注的。
透過覆寫 fields() 和/或 extraFields(),您可以指定資源中哪些資料(稱為欄位)可以放入其陣列表示形式中。這兩種方法之間的區別在於,前者指定應包含在陣列表示形式中的預設欄位集,而後者指定如果終端使用者透過 expand
查詢參數請求它們,則可以包含在陣列中的其他欄位。例如:
// returns all fields as declared in fields()
http://127.0.0.1/users
// only returns "id" and "email" fields, provided they are declared in fields()
http://127.0.0.1/users?fields=id,email
// returns all fields in fields() and field "profile" if it is in extraFields()
http://127.0.0.1/users?expand=profile
// returns all fields in fields() and "author" from post if
// it is in extraFields() of post model
http://127.0.0.1/comments?expand=post.author
// only returns "id" and "email" provided they are in fields() and "profile" if it is in extraFields()
http://127.0.0.1/users?fields=id,email&expand=profile
fields()
¶預設情況下,yii\base\Model::fields() 會傳回所有模型屬性作為欄位,而 yii\db\ActiveRecord::fields() 僅傳回從資料庫填入的屬性。
您可以覆寫 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_key
、password_hash
和password_reset_token
。
extraFields()
¶預設情況下,yii\base\Model::extraFields() 會傳回空陣列,而 yii\db\ActiveRecord::extraFields() 則會傳回從資料庫填入的關聯名稱。
extraFields()
的傳回資料格式與 fields()
相同。通常,extraFields()
主要用於指定值為物件的欄位。例如,給定以下欄位宣告:
public function fields()
{
return ['id', 'email'];
}
public function extraFields()
{
return ['profile'];
}
帶有 https://127.0.0.1/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 上編輯 !
註冊 或 登入 以發表評論。