Контроллеры (Controller)

Контроллеры являются частью архитектуры MVC и объектами классов, проходящих в yii\base\Controller и отвечающих за обработку запросов, а также генерацию ответов. После принятия на себя управление от приложений, контроллеры анализируют поступающие данных запроса, передают их к моделям, вводят результаты модели в представления и генерируют исходящие ответы.

Действия

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

В следующем примере показан post контроллер с двумя действиями – view и create:

namespace app\controllers;

use Yii;
use app\models\Post;
use yii\web\Controller;
use yii\web\NotFoundHttpException;

class PostController extends Controller
{
    public function actionView($id)
    {
        $model = Post::findOne($id);
        if ($model === null) {
            throw new NotFoundHttpException;
        }

        return $this->render('view', [
            'model' => $model,
        ]);
    }

    public function actionCreate()
    {
        $model = new Post;

        if ($model->load(Yii::$app->request->post()) && $model->save()) {
            return $this->redirect(['view', 'id' => $model->id]);
        } else {
            return $this->render('create', [
                'model' => $model,
            ]);
        }
    }
}

В действии view (определяется методом actionView()) код сначала загружает запрашиваемую модель. Если модель успешно загружена, то можно использовать ее данные для передачи и отображения в представлении. В противном случае будет брошено исключение.

В действии create (определяется методом actionCreate()) код пытается заполнить экземпляр модели, используя данные запроса и сохранения модели. Если попытка успешна, то произойдет перенаправление браузера на действие view с идентификаторов созданной записи. В противном случае страница останется в действии create, где пользователи могут снова ввести необходимые данные для отправки.

Маршруты

Конечные пользователи  обращаются через действия так называемых маршрутов. Маршрут представляет собой строку, которая состоит из следующих частей:

  • Идентификатор модуля - существует тогда, когда контроллер принадлежит к модулю.
  • Идентификатор контроллера - идентифицирует контроллер между всеми контроллерами в пределах одного приложения.
  • Идентификатор действия - идентифицирует действие среди всех других действий в рамках используемого контроллера.

Маршруты имеют следующий формат:

ControllerID/ActionID

или следующий формат, если контроллер принадлежит к модулю:

ModuleID/ControllerID/ActionID

Таким образом, если пользователь запрашивает с URL http://hostname/index.php?r=site/index, действие index в контроллере сайта будет выполняться.

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

В веб-приложениях, контроллеры должны проходить от yii\web\Controller или его дочерних классов. Аналогичным образом, в консольных приложениях, контроллеры должны проходить от yii\console\Controller или его дочерних классов. Следующий код определяет контроллер site:

namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
}

Идентификатор контроллера

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

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

ID контроллера может также содержать префикс подкаталога. Например, admin/article обозначает контроллер статей в поддиректории admin под пространством имен контроллера. Допустимые символы для префиксов вложенных каталогов: английские буквы в нижнем и верхнем регистре, цифры, подчеркивания и косые черты, где прямые слэши используются как разделители для многоуровневых подкаталогов (например, panel/admin).

Имена контроллеров

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

  1. Поверните первую букву в каждом слове, разделенную дефисом, в верхний регистр. Обратите внимание: если идентификатор контроллера содержит косые черты, это правило применяется только к части после последней косой черты в идентификаторе.
  2. Удалите дефисы и замените любые косые черты на обратные косые черты.
  3. Добавьте суффикс Controller
  4. Подготовьте пространство имен контроллера.

Карта контроллера

Вы можете настроить карту контроллера, чтобы преодолеть ограничения идентификаторов контроллеров и названий классов, описанных выше. Это особенно полезно, когда вы используете сторонние контроллеры, и у вас нет контроля над именами их классов.

Вы можете настроить карту контроллера в конфигурации приложения. Например:

[
    'controllerMap' => [
        // Объявляет контроллер «account» с использованием имени класса
        'account' => 'app\controllers\UserController',

        // Объявляет контроллер «article» с помощью массива конфигурации
        'article' => [
            'class' => 'app\controllers\PostController',
            'enableCsrfValidation' => false,
        ],
    ],
]

Контроллер по умолчанию

Каждое приложение имеет контроллер по умолчанию, указанный в свойстве yii\base\Application::$defaultRoute. Когда запрос не указывает маршрут, будет использоваться маршрут, указанный этим свойством. Для веб-приложений его значением является «site», а для консольных приложений - help. Поэтому, если URL-адрес - http: //hostname/index.php, тогда контроллер сайта будет обрабатывать запрос.

Вы можете изменить контроллер по умолчанию со следующей конфигурацией приложения:

[
    'defaultRoute' => 'main',
]

Создание действий

Создание действий может быть таким же простым, как определение так называемых методов действий в классе контроллера. Метод действия - это публичный метод, имя которого начинается со слова action. Возвращаемое значение метода действия представляет данные ответа, которые должны быть отправлены конечным пользователям. Следующий код определяет два действия: index и hello-world:

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex()
    {
        return $this->render('index');
    }

    public function actionHelloWorld()
    {
        return 'Hello World';
    }
}

Идентификаторы действий

Действие часто предназначено для выполнения конкретной манипуляции с ресурсом. По этой причине идентификаторы действий обычно являются глаголами, например, view, update и т.д.

По умолчанию идентификаторы действий должны содержать только эти символы: английские буквы в нижнем регистре, цифры, символы подчеркивания и дефисы (вы можете использовать дефисы для разделения слов). Например, view, update2 и comment-post являются действительными идентификаторами действий.

Вы можете создавать действия двумя способами: встроенными и автономными. Встраиваемое действие определяется как метод в классе контроллера, в то время как автономное действие - это класс, расширяющий yii\base\Action или его дочерние классы. Встроенные действия требуют меньше усилий для создания и часто предпочтительнее, если у вас нет намерения повторно использовать эти действия. С другой стороны, автономные действия в основном создаются для использования в разных контроллерах или перераспределяются как расширения.

Встроенные действия

Вложенные действия относятся к действиям, которые определены в терминах методов действий, как мы только что описали. Имена методов действий получают из идентификаторов действий в соответствии со следующей процедурой:

  1. Поверните первую букву в каждом слове идентификатора действия в верхний регистр.
  2. Удалите дефисы.
  3. Подготовьте префикс action

Например, index становится actionIndex, а hello-world становится действием HelloWorld.

Встроенные действия являются наиболее часто определяемыми действиями, поскольку они не требуют особых усилий для их создания. Однако если вы планируете повторное использование одного и того же действия в разных местах или хотите перераспределить действие, вам следует рассмотреть его как автономное действие.

Автономные действия

Автономные действия определяются в терминах классов действий, расширяющих yii\base\Action или его дочерние классы. Например, в выпусках Yii есть yii\web\ViewAction и yii\web\ErrorAction, оба из которых являются автономными действиями. Чтобы использовать автономное действие, вы должны объявить его в карте действий, переопределив метод yii\base\Controller::actions() в ваших классах контроллера, например:

public function actions()
{
    return [
        // Объявляет действие «error» с использованием имени класса
        'error' => 'yii\web\ErrorAction',

        // Объявляет действие «view» с использованием массива конфигурации
        'view' => [
            'class' => 'yii\web\ViewAction',
            'viewPrefix' => '',
        ],
    ];
}

Как вы можете видеть, метод actions() должен возвращать массив, ключи которого являются идентификаторами действия и значениями соответствующих имен или конфигураций классов действий. В отличие от встроенных действий, идентификаторы действий для автономных действий могут содержать произвольные символы, если они объявлены в методе actions().

Чтобы создать автономный класс действия, вы должны расширить yii\base\Action или дочерний класс и реализовать открытый метод run(). Роль метода run() аналогична роли метода действия. Например:

<?php
namespace app\components;

use yii\base\Action;

class HelloWorldAction extends Action
{
    public function run()
    {
        return "Hello World";
    }
}

Результаты действий

Возвращаемое значение метода действия или метода run() автономного действия имеет значение. Это означает результат соответствующего действия. Возвращаемое значение может быть объектом ответа, который будет отправлен конечному пользователю в качестве ответа.

  • Для веб-приложений возвращенное значение может также представлять собой произвольные данные, которые будут присвоены yii\web\Response::$data и далее преобразованы в строку, представляющую тело ответа.
  • Для консольных приложений возвращаемое значение может также быть целым числом, представляющим статус завершения выполнения команды.

В примерах, показанных выше, результатом действия являются все строки, которые будут рассматриваться как тело ответа, отправляемое конечным пользователям. В следующем примере показано, как действие может перенаправить браузер пользователя на новый URL-адрес, возвратив объект ответа (потому что метод redirect() возвращает объект ответа):

public function actionForward()
{
    // перенаправление браузера пользователя на http://example.com
    return $this->redirect('http://example.com');
}

Параметры действия

Методы действий для встроенных действий и методы run() для автономных действий могут принимать параметры, называемые параметрами действия. Их значения получены из запросов. Для веб-приложений значение каждого параметра действия извлекается из $ _GET, используя имя параметра в качестве ключа. Для консольных приложений они соответствуют аргументам командной строки.

В следующем примере действие view (встроенное действие) объявило два параметра: $id и $version.

namespace app\controllers;

use yii\web\Controller;

class PostController extends Controller
{
    public function actionView($id, $version = null)
    {
        // ...
    }
}