# Контроллеры ¶

После создания классов ресурсов и настройки способа форматирования ресурсных данных следующим шагом является создание действий контроллеров для предоставления ресурсов конечным пользователям через 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).