Ресурсы
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]] реализует мощный функционал для работы с БД, будет полезным если данные ресурса хранятся в поддерживаемых БД.
В этом разделе, мы опишем как использовать методы наследуемые вашим класом ресурсов от [yii\base\Model] необходимые RESTful API.
Если класс ресурса не наследуется от [[yii\base\Model]], то будут возвращены все public поля.
Поля
Когда ресурс включается в ответ RESTful API, необходимо представить(сеарилизовать) ресурс как строку. Yii разбивает процесс сеарилизации на два шага. На первом шаге, ресурс конвертируется в массив [[yii\rest\Serializer]]. На втором шаге, массив сеарилизуется в строку в требуемом формате (JSON, XML) при помощи [[yii\web\ResponseFormatterInterface|интерфейса для форматирования ответа]]. Это сделано для того чтобы при разработке вы могли сосредоточится на разработке класса ресурсов.
При переопределении методов [[yii\base\Model::fields()|fields()]] и/или [[yii\base\Model::extraFields()|extraFields()]], вы можете указать какие данные будут отображаться при представлении в виде массива. Разница между этими двумя методами в том, что первый определяет стандартный набор полей которые будут включены в представлении массивом, а второй определяет дополнительные поля, которые могут быть включены в массив если запрос пользователя к ресурсу использует дополнительные параметры. Например:
// вернёт все поля объявленные в fields()
http://localhost/users
// вернёт только поля id и email, если они объявлены в методе fields()
http://localhost/users?fields=id,email
// вернёт все поля обявленные в fields() и поле profile если оно указано в extraFields()
http://localhost/users?expand=profile
// вернёт только id, email и profile, если они объявлены в fields() и extraFields()
http://localhost/users?fields=id,email&expand=profile
fields()
Переопределение По умолчанию, [[yii\base\Model::fields()]] вернёт все атрибуты модели как поля, пока что [[yii\db\ActiveRecord::fields()]] возвращает только те атрибуты которые были объявлены в схеме БД.
Вы можете переопределить fields()
при этом добавить, удалить, переименовать или переобъявить поля. Возвращаемое значение fields()
должно быть массивом. Ключи массива это имена полей, и значения массива могут быть именами свойств/атрибутов или анонимных функций, возвращающих соответсвующее значение полей.
Если имя атрибута такое же, как ключ массива вы можете не заполнять значение. Например:
// явное перечисление всех атрибутов, лучше всего использовать когда вы хотите убедиться что изменение
// таблицы БД или атрибутов модели не повлияет на изменение полей в представлении для API (для поддержки обратной совместимости с API).
public function fields()
{
return [
// название поля совпадает с названием атрибута
'id',
// ключ массива "email", соответсвует значению атрибута "email_address"
'email' => 'email_address',
// ключ массива "name", это PHP callback функция возвращающая значение
'name' => function () {
return $this->first_name . ' ' . $this->last_name;
},
];
}
// Для фильтрации полей лучше всего использовать, поля наследуемые от родительского класса
// и blacklist для не безопасных полей.
public function fields()
{
$fields = parent::fields();
// удаляем не безопасные поля
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'];
}
запрос http://localhost/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. Ваши классы ресурсов могу поддерживать HATEOAS реализуя [[yii\web\Linkable]] интерфейс. Интерфейс реализует один метод [[yii\web\Linkable::getLinks()|getLinks()]] который возвращает список [[yii\web\Link|links]]. Вы должны вернуть существующий URL на метод ресурса. Например:
use yii\db\ActiveRecord;
use yii\web\Link;
use yii\web\Linkable;
use yii\helpers\Url;
class User extends ActiveRecord implements Linkable
{
public function getLinks()
{
return [
Link::REL_SELF => Url::to(['user/view', 'id' => $this->id], true),
];
}
}
При отправке ответа объект User
будет содержать поле _links
содержащий ссылки связанные с объектом User
.
Например:
{
"id": 100,
"email": "user@example.com",
// ...
"_links" => [
"self": "https://example.com/users/100"
]
}
Коллекции
Объекты ресурсов могут групироваться в коллекции. Каждая коллекция включает список объектов ресурсов одного типа.
Так как коллекции представляются в виде массива, их удобнее использовать как проводник данных. Так как проводник данных поддерживает операции сортировки, разбиения на страницы это удобно использовать для 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
: Количество ресурсов отображаемых на 1 странице; -
Link
: Набор ссылок позволяющий клиенту пройти все ресурсы, страница за страницей.
Примеры вы можете найти в разделе Быстрый старт.