RESTful контроллеры Yii 2
RESTful контроллеры Yii 2

Контроллеры

После создания классов ресурсов и настройки способа форматирования ресурсных данных следующим шагом является создание действий контроллеров для предоставления ресурсов конечным пользователям через RESTful API.

В Yii есть два базовых класса контроллеров для упрощения вашей работы по созданию RESTful-действий: [[yii\rest\Controller]] и [[yii\rest\ActiveController]]. Разница между этими двумя контроллерами в том, что у последнего есть набор действий по умолчанию, который специально создан для работы с ресурсами, представленными Active Record. Так что если вы используете Active Record и вас устраивает предоставленный набор встроенных действий, вы можете унаследовать классы ваших контроллеров от [[yii\rest\ActiveController]], что позволит вам создать полноценные RESTful API, написав минимум кода.

Старт! Честный VDS/VPS, на котором «Лунная База» живет уже 20+ лет

Задумываетесь о том, чтобы поднять свой pet-проект, сайт клиента или настроить окружение для разработки? Уже пора подумать, где арендовать железо.

Лунная База хостится на FirstVDS более 20 лет. Мыслей о том, чтобы перебраться на другой хостинг, не было ни разу (хотя опыт работы с другими вариантами, конечно, есть).

Бывали разные ситуации, но они бывают на любом железе. Главное, что нужно понять: здесь нет маркетинговой шелухи и сказок про «мы всё сделаем за вас». Если вы берете VDS — вам дают полный root, возможность накатить любую ОС и не лезут в ваши конфиги.

Если в саппорт написать с вопросом по вашему коду и получить ответ: «Читайте документацию и разбирайтесь сами» или «Обратитесь к профильному специалисту» — это не повод обижаться. Это повод углубить свои знания в DevOps и сайтостроении! Бегите от тех, кто пообещает: «Мы всё чиним и настраиваем абсолютно бесплатно!». Никто никогда не работает «по доброте душевной» в ущерб себе, а бесплатный сыр в администрировании обычно заканчивается сломанной базой данных.

Что по факту: Гибкое масштабирование ядер и RAM, экономия по сравнению с физическими серверами и адекватная панель ispmanager, если она вам нужна.



[[yii\rest\Controller]] и [[yii\rest\ActiveController]] имеют следующие возможности, некоторые из которых будут подробно описаны в следующих разделах:

[[yii\rest\ActiveController]], кроме того, предоставляет следующие возможности:

  • Набор наиболее часто используемых действий: index, view, create, update, delete и options;
  • Авторизация пользователя для запрашиваемых действия и ресурса.

Создание классов контроллеров

При создании нового класса контроллера в имени класса обычно используется название типа ресурса в единственном числе. Например, контроллер, отвечающий за предоставление информации о пользователях, можно назвать UserController.

Создание нового действия похоже на создание действия для Web-приложения. Единственное отличие в том, что в RESTful-действиях вместо рендера результата в представлении с помощью вызова метода render() вы просто возвращаете данные. Выполнение преобразования исходных данных в запрошенный формат ложится на [[yii\rest\Controller::serializer|сериализатор]] и [[yii\web\Response|объект ответа]]. Например:

public function actionView($id)
{
    return User::findOne($id);
}

Фильтры

Большинство возможностей RESTful API, предоставляемых [[yii\rest\Controller]], реализовано на основе фильтров. В частности, следующие фильтры будут выполняться в том порядке, в котором они перечислены:

  • [[yii\filters\ContentNegotiator|contentNegotiator]]: обеспечивает согласование содержимого, более подробно описан в разделе Форматирование ответа;
  • [[yii\filters\VerbFilter|verbFilter]]: обеспечивает проверку HTTP-метода;
  • [[yii\filters\auth\AuthMethod|authenticator]]: обеспечивает аутентификацию пользователя, более подробно описан в разделе Аутентификация;
  • [[yii\filters\RateLimiter|rateLimiter]]: обеспечивает ограничение частоты запросов, более подробно описан в разделе Ограничение частоты запросов.

Эти именованные фильтры объявлены в методе [[yii\rest\Controller::behaviors()|behaviors()]]. Вы можете переопределить этот метод для настройки отдельных фильтров, отключения каких-либо из них или для добавления ваших собственных фильтров. Например, если вы хотите использовать только базовую HTTP-аутентификацию, вы можете написать такой код:

use yii\filters\auth\HttpBasicAuth;

public function behaviors()
{
    $behaviors = parent::behaviors();
    $behaviors['authenticator'] = [
        'class' => HttpBasicAuth::className(),
    ];
    return $behaviors;
}

CORS

Добавление фильтра совместного использования ресурсов между источниками в контроллер немного сложнее, чем добавление других фильтров, описанных выше, поскольку фильтр CORS должен применяться перед методами аутентификации и, следовательно, требует немного другого подхода по сравнению с другими фильтрами. Также аутентификация должна быть отключена для запросов CORS Preflight, чтобы браузер мог безопасно определить, можно ли сделать запрос заранее без необходимости отправки учетных данных аутентификации. Ниже приведен код, необходимый для добавления фильтра [[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]], вам следует установить значение его свойства [[yii\rest\ActiveController::modelClass|modelClass]] равным имени класса ресурса, который вы планируете обслуживать с помощью этого контроллера. Класс ресурса должен быть унаследован от [[yii\db\ActiveRecord]].

Настройка действий

По умолчанию [[yii\rest\ActiveController]] предоставляет набор из следующих действий:

  • [[yii\rest\IndexAction|index]]: постраничный список ресурсов;
  • [[yii\rest\ViewAction|view]]: возвращает подробную информацию об указанном ресурсе;
  • [[yii\rest\CreateAction|create]]: создание нового ресурса;
  • [[yii\rest\UpdateAction|update]]: обновление существующего ресурса;
  • [[yii\rest\DeleteAction|delete]]: удаление указанного ресурса;
  • [[yii\rest\OptionsAction|options]]: возвращает поддерживаемые HTTP-методы.

Все эти действия объявляются в методе [[yii\rest\ActiveController::actions()|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]] эта задача может быть решена переопределением метода [[yii\rest\ActiveController::checkAccess()|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]]. Если вы создаёте новые действия и хотите в них выполнять контроль доступа, вы должны вызвать этот метод явно в своих новых действиях.

Tip: вы можете реализовать метод checkAccess() с помощью "Контроля доступа на основе ролей" (RBAC).

Самый честный хостинг за 20+ лет существования Лунной Базы

Задумываешься о том, чтобы поднять свой сайт в Интернете? Уже пора подумать о том, какой хостинг выбрать?

Лунная База хостится 20+ лет на firstDVS. При этом, мыслей о том, чтобы перебраться на другой хостинг не было. (Но, при этом есть опыт работы с другими вариантами.)

Бывали с firstDVS разные ситуации, но, они бывают на всех хостингах. Единственное, что тут важно понять, - это то, что никто ничего тебе не будет впаривать... Но, и работать за тебя тоже никто не станет. Если в саппорт ответили: «Читайте по ссылке и разбирайтесь сами...» или вообще «Обратитесь за помощью к специалисту», - это повод углубить свои знания в области сайтостроения, а не бежать к тем, что пообещают: «Мы всё чиним и всё делаем за своих клиентов абсолютно бесплатно!» Никто никогда ничего ни за кого "по доброте душевной" не делал, не делает и не будет делать!

Старт! Горячий старт на просторы интернета
Старт! Горячий старт на просторы интернета
Старт! Меню