Контроллеры ¶
После создания классов ресурсов и настройки способа форматирования ресурсных данных следующим шагом является создание действий контроллеров для предоставления ресурсов конечным пользователям через 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
.
Создание нового действия похоже на создание действия для Web-приложения. Единственное отличие в том,
что в RESTful-действиях вместо рендера результата в представлении с помощью вызова метода render()
вы просто возвращаете данные. Выполнение преобразования исходных данных в запрошенный формат ложится на
сериализатор и объект ответа.
Например:
public function actionView($id)
{
return User::findOne($id);
}
Фильтры ¶
Большинство возможностей RESTful API, предоставляемых yii\rest\Controller, реализовано на основе фильтров. В частности, следующие фильтры будут выполняться в том порядке, в котором они перечислены:
- contentNegotiator: обеспечивает согласование содержимого, более подробно описан в разделе Форматирование ответа;
- verbFilter: обеспечивает проверку HTTP-метода;
- authenticator: обеспечивает аутентификацию пользователя, более подробно описан в разделе Аутентификация;
- rateLimiter: обеспечивает ограничение частоты запросов, более подробно описан в разделе Ограничение частоты запросов.
Эти именованные фильтры объявлены в методе behaviors(). Вы можете переопределить этот метод для настройки отдельных фильтров, отключения каких-либо из них или для добавления ваших собственных фильтров. Например, если вы хотите использовать только базовую HTTP-аутентификацию, вы можете написать такой код:
use yii\filters\auth\HttpBasicAuth;
public function behaviors()
{
$behaviors = parent::behaviors();
$behaviors['authenticator'] = [
'class' => HttpBasicAuth::className(),
];
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();
// отключить действия "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. Если вы создаёте
новые действия и хотите в них выполнять контроль доступа, вы должны вызвать этот метод явно в своих новых действиях.
Подсказка: вы можете реализовать метод
checkAccess()
с помощью "Контроля доступа на основе ролей" (RBAC).