Контроллеры
После создания классов ресурсов и указания того, как данные ресурсов должны форматироваться, следующим шагом является создание действий контроллера для экспонирования ресурсов конечным пользователям через RESTful API.
Yii предоставляет два базовых класса контроллеров для упрощения создания RESTful действий: yii\rest\Controller и yii\rest\ActiveController. Разница между этими двумя контроллерами заключается в том, что последний предоставляет набор действий по умолчанию, специально предназначенных для работы с ресурсами, представленными как Active Record. Поэтому, если вы используете Active Record и вам удобны предоставленные встроенные действия, вы можете рассмотреть возможность расширения ваших классов контроллеров от yii\rest\ActiveController, что позволит вам создавать мощные RESTful API с минимальным кодом.
Оба yii\rest\Controller и yii\rest\ActiveController предоставляют следующие функции, некоторые из которых будут подробно описаны в следующих разделах:
- Проверка HTTP-методов;
- Переговоры по содержимому и форматирование данных;
- Аутентификация;
- Ограничение скорости.
yii\rest\ActiveController дополнительно предоставляет следующие функции:
- Набор часто используемых действий:
index,view,create,update,delete,options; - Авторизация пользователя по отношению к запрошенному действию и ресурсу.
Создание классов контроллеров
При создании нового класса контроллера принято использовать тип имени ресурса в единственном числе. Например, для предоставления информации о пользователях контроллер может быть назван как UserController.
Создание нового действия аналогично созданию действия для веб-приложения. Единственное отличие заключается в том, что вместо рендеринга результата с помощью представления, вызывая метод render(), для RESTful действий вы напрямую возвращаете данные. Сериализатор и объект ответа будут обрабатывать преобразование исходных данных в запрошенный формат. Например,
public function actionView($id)
{
return User::findOne($id);
}
Фильтры
Большинство функций RESTful API, предоставляемых yii\rest\Controller, реализованы в терминах фильтров. В частности, следующие фильтры будут выполняться в порядке их перечисления:
- contentNegotiator: поддерживает переговоры по содержимому, о которых будет рассказано в разделе Форматирование ответа;
- verbFilter: поддерживает проверку HTTP-методов;
- authenticator: поддерживает аутентификацию пользователя, о которой будет рассказано в разделе Аутентификация;
- rateLimiter: поддерживает ограничение скорости, о котором будет рассказано в разделе Ограничение скорости.
Эти именованные фильтры объявляются в методе behaviors(). Вы можете переопределить этот метод для настройки отдельных фильтров, отключения некоторых из них или добавления собственных фильтров. Например, если вы хотите использовать только аутентификацию по HTTP Basic, вы можете написать следующий код:
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(),
];
return $behaviors;
}
CORS
Добавление фильтра Cross-Origin Resource Sharing в контроллер немного сложнее, чем добавление других фильтров, описанных выше, так как 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::className(),
];
// 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. Если вы создаёте новые действия и также хотите выполнить проверку доступа, вы должны явно вызвать этот метод в новых действиях.
Совет: Вы можете реализовать
checkAccess()с помощью компонента управления доступом на основе ролей (RBAC).
© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-rest-controllers.html