Spec-Zone.ru › Yii 2.0

Контроллеры

  1. Действия
  2. Маршруты
  3. Создание контроллеров
  4. Создание действий
  5. Жизненный цикл контроллера
  6. Рекомендации по практическому применению

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

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

Маршруты

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

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

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

ControllerID/ActionID

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

ModuleID/ControllerID/ActionID

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

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

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

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
}

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

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

По умолчанию идентификаторы контроллеров должны содержать только следующие символы: английские буквы в нижнем регистре, цифры, символы подчеркивания, тире и косые черты. Например, article и post-comment являются допустимыми идентификаторами контроллеров, в то время как article?, PostComment, admin\post — нет.

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

Наименование классов контроллеров

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

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

Ниже приведены некоторые примеры, предполагая, что пространство имен контроллеров принимает значение по умолчанию app\controllers:

  • article становится app\controllers\ArticleController;
  • post-comment становится app\controllers\PostCommentController;
  • admin/post-comment становится app\controllers\admin\PostCommentController;
  • adminPanels/post-comment становится app\controllers\adminPanels\PostCommentController.

Классы контроллеров должны быть автозагружаемыми. По этой причине в приведенных выше примерах класс контроллера article должен быть сохранен в файле с алиасом @app/controllers/ArticleController.php; в то время как контроллер admin/post-comment должен быть в @app/controllers/admin/PostCommentController.php.

Информация: Последний пример admin/post-comment показывает, как можно поместить контроллер в подкаталог пространства имен контроллеров. Это полезно, когда вы хотите организовать контроллеры в несколько категорий и не хотите использовать модули.

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

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

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

[
    'controllerMap' => [
        // declares "account" controller using a class name
        'account' => 'app\controllers\UserController',

        // declares "article" controller using a configuration array
        'article' => [
            'class' => 'app\controllers\PostController',
            'enableCsrfValidation' => false,
        ],
    ],
]

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

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

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

[
    '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 являются допустимыми идентификаторами действий, в то время как view? и Update — нет.

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

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

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

Имена методов действий выводятся из идентификаторов действий в соответствии со следующим алгоритмом:

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

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

Примечание: Имена методов действий чувствительны к регистру. Если у вас есть метод с именем ActionIndex, он не будет рассматриваться как метод действия, и в результате запрос на действие index приведет к исключению. Также обратите внимание, что методы действий должны быть публичными. Приватный или защищенный метод НЕ определяет встроенное действие.

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

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

Автономные действия определяются в терминах классов действий, расширяющих yii\base\Action или его дочерние классы. Например, в выпусках Yii есть yii\web\ViewAction и yii\web\ErrorAction, которые являются автономными действиями.

Чтобы использовать автономное действие, вы должны объявить его в карте действий, переопределив метод yii\base\Controller::actions() в ваших классах контроллеров, как показано ниже:

public function actions()
{
    return [
        // declares "error" action using a class name
        'error' => 'yii\web\ErrorAction',

        // declares "view" action using a configuration array
        '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()
{
    // redirect the user browser to 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)
    {
        // ...
    }
}

Параметры действия будут заполняться следующим образом для различных запросов:

  • http://hostname/index.php?r=post/view&id=123: параметр $id будет заполнен значением '123', в то время как $version по-прежнему null, так как нет параметра запроса version.
  • http://hostname/index.php?r=post/view&id=123&version=2: параметры $id и $version будут заполнены значениями '123' и '2' соответственно.
  • http://hostname/index.php?r=post/view: будет выброшено исключение yii\web\BadRequestHttpException, так как обязательный параметр $id отсутствует в запросе.
  • http://hostname/index.php?r=post/view&id[]=123: будет выброшено исключение yii\web\BadRequestHttpException, так как параметр $id получает неожиданное значение массива ['123'].

Если вы хотите, чтобы параметр действия принимал значения массива, вы должны указать тип с помощью array, как в следующем примере:

public function actionView(array $id, $version = null)
{
    // ...
}

Теперь, если запрос — http://hostname/index.php?r=post/view&id[]=123, параметр $id получит значение ['123']. Если запрос — http://hostname/index.php?r=post/view&id=123, параметр $id по-прежнему получит то же значение массива, потому что скалярное значение '123' автоматически преобразуется в массив.

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

Действие по умолчанию

В каждом контроллере задано действие по умолчанию, которое указывается через свойство yii\base\Controller::$defaultAction. Когда маршрут содержит только идентификатор контроллера, это означает, что запрашивается действие по умолчанию указанного контроллера.

По умолчанию действие по умолчанию установлено как index. Если вы хотите изменить значение по умолчанию, просто переопределите это свойство в классе контроллера, как показано ниже:

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
    public $defaultAction = 'home';

    public function actionHome()
    {
        return $this->render('home');
    }
}

Жизненный цикл контроллера

При обработке запроса приложение создаст контроллер на основе запрошенного маршрута. Затем контроллер пройдет следующий жизненный цикл для выполнения запроса:

  1. Метод yii\base\Controller::init() вызывается после создания и настройки контроллера.
  2. Контроллер создает объект действия на основе запрошенного идентификатора действия:
    • Если идентификатор действия не указан, используется идентификатор действия по умолчанию.
    • Если идентификатор действия найден в карте действий, создается автономное действие;
    • Если идентификатор действия соответствует методу действия, создается встроенное действие;
    • В противном случае будет выброшено исключение yii\base\InvalidRouteException.
  3. Контроллер последовательно вызывает метод beforeAction() приложения, модуля (если контроллер принадлежит модулю) и контроллера.
    • Если одно из вызовов возвращает false, остальные невызванные методы beforeAction() будут пропущены, и выполнение действия будет отменено.
    • По умолчанию каждый вызов метода beforeAction() запускает событие beforeAction, к которому вы можете прикрепить обработчик.
  4. Контроллер выполняет действие.
    • Параметры действия будут проанализированы и заполнены данными из запроса.
  5. Контроллер последовательно вызывает метод afterAction() контроллера, модуля (если контроллер принадлежит модулю) и приложения.
    • По умолчанию каждый вызов метода afterAction() запускает событие afterAction, к которому вы можете прикрепить обработчик.
  6. Приложение получит результат действия и назначит его объекту ответа.

Рекомендации

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

Вот некоторые конкретные рекомендации. Контроллеры

  • могут получить доступ к данным запроса;
  • могут вызывать методы моделей и других компонентов сервисов с данными запроса;
  • могут использовать представления для создания ответов;
  • не должны обрабатывать данные запроса — это нужно делать в слое модели;
  • должны избегать встраивания HTML или другого кода представления — это лучше делать в представлениях.

© 2008–2017 by Yii Software LLC
Licensed under the three clause BSD license.
http://www.yiiframework.com/doc-2.0/guide-structure-controllers.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API