Kontrolyor MVC arxitekturasining bir qismi hisoblanadi. Bu yii\base\Controller klassidan voris qilib yaratilgan klass obyektlaridir, ushbu obyektlar so'rovlarni (request) qayta ishlash va javoblarni (response) tayyorlash uchun mo'ljallangan. Ilova (application) so'rovlarni qayta ishlagandan so'ng, so'rovlarga mos kontrolyor obyektlarini yaratadi va bu obyektlar kiruvchi ma'lumotlarni tahlil qiladi hamda ushbu ma'lumotlarni modelga jo'natadi so'ng modeldan olingan natijalarni namoyish (view)ga joylashtiradi va oxirgi natijani hosil qiladi.
Kontrolyorlar amallar (action)dan tashkil topadi, amallar asosiy bloklar hisoblanib, foydalanuvchilar amallarga murojaat qilishi mumkin va ma'lum buyruqlar bajarilib natija hosil qilinadi hamda natija foydalanuvchiga qaytariladi. Bitta kontrolyorda bitta va undan ortiq amal bo'lishi mumkin.
Quyidagi misolda ikkita amaldan (view
va create
) tashkil topgan post
kontrolyori keltirilgan:
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()
), код сначала загружает модель
согласно запрошенному ID модели; Если модель успешно загружена, то код отобразит ее с помощью представления
под названием view
. В противном случае будет брошено исключение.
В действии create
(определенном методом actionCreate()
), код аналогичен. Он сначала пытается загрузить модель
с помощью данных из запроса и сохранить модель. Если все прошло успешно, то код перенаправляет браузер на действие view
с ID только
что созданной модели. В противном случае он отобразит представление create
, через которое пользователь может заполнить нужные данные.
Конечные пользователи обращаются к действиям через так называемые маршруты. Маршрут это строка, состоящая из следующих частей:
Маршруты могут иметь следующий формат:
ControllerID/ActionID
или следующий формат, если контроллер принадлежит модулю:
ModuleID/ControllerID/ActionID
Таким образом, если пользователь запрашивает URL https://hostname/index.php?r=site/index
, то index
действие в site
контроллере будет вызвано.
Секция Маршрутизация содержит более подробную информацию о том как маршруты сопоставляются с действиями.
В Веб приложениях, контроллеры должны быть унаследованы от yii\web\Controller или его потомков.
Аналогично для консольных приложений, контроллеры должны быть унаследованы от yii\console\Controller или
его потомков. Следующий код определяет site
контроллер:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
}
Обычно контроллер сделан таким образом, что он должен обрабатывать запросы, связанные с определенным ресурсом.
Именно по этим причинам, ID контроллеров обычно являются существительные, ссылающиеся на ресурс, который они обрабатывают.
Например, вы можете использовать article
в качестве ID контроллера, которые отвечает за обработку данных статей.
По-умолчанию, ID контроллеров должны содержать только следующие символы: Английские буквы в нижнем регистре, цифры, подчеркивания,
тире и слэш. Например, оба article
и post-comment
являются допустимыми ID контроллеров, в то время как article?
, PostComment
,
admin\post
не являются таковыми.
ID контроллеров также могут содержать префикс подпапки. Например, в admin/article
часть article
является контроллером в
подпапке admin
в пространстве имен контроллеров.
Допустимыми символами для префиксов подпапок являются: Английские буквы в нижнем и верхнем регистре, символы подчеркивания и
слэш, где слэш используется в качестве разграничителя для многовложенных подпапок (например panels/admin
).
Названия классов контроллеров могут быть получены из ID контроллеров следующими способами:
Controller
;Ниже приведены несколько примеров, с учетом того, что пространство имен контроллеров
имеет значение по умолчанию равное 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
показывает каким образом вы можете расположить контроллер в подпапке пространства имен контроллеров. Это очень удобно, когда вы хотите организовать свои контроллеры в несколько категорий и не хотите использовать модули.
Вы можете сконфигурировать карту контроллеров для того, чтобы преодолеть описанные выше ограничения именования ID контроллеров и названий классов. В основном это очень удобно, когда вы используете сторонние контроллеры, именование которых вы не можете контролировать.
Вы можете сконфигурировать карту контроллеров в настройках приложения следующим образом:
[
'controllerMap' => [
[
// объявляет "account" контроллер, используя название класса
'account' => 'app\controllers\UserController',
// объявляет "article" контроллер, используя массив конфигурации
'article' => [
'class' => 'app\controllers\PostController',
'enableCsrfValidation' => false,
],
],
],
]
Каждое приложение имеет контроллер по умолчанию, указанный через свойство yii\base\Application::$defaultRoute.
Когда в запросе не указан маршрут, тогда будет использован маршрут указанный в данном свойстве.
Для Веб приложений, это значение 'site'
, в то время как для консольных приложений,
это 'help'
. Таким образом, если задан URL https://hostname/index.php
, это означает, что контроллер site
выполнит обработку запроса.
Вы можете изменить контроллер по умолчанию следующим образом в настройках приложения:
[
'defaultRoute' => 'main',
]
Создание действий не представляет сложностей также как и объявление так называемых методов действий в классе контроллера. Метод действия
это public метод, имя которого начинается со слова 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';
}
}
В основном действие разрабатывается для какой-либо конкретной обработки ресурса. По этой причине, ID действий в основном
являются глаголами, такими как view
, update
, и т. д.
По-умолчанию, ID действия должен содержать только следующие символы: Английские буквы в нижнем регистре, цифры,
подчеркивания и дефисы. Дефисы в ID действий используются для разделения слов. Например, view
, update2
, comment-post
являются
допустимыми ID действий, в то время как view?
, Update
не являются таковыми.
Вы можете создавать действия двумя способами: встроенные действия и отдельные действия. Встроенное действие является методом, определенным в классе контроллера, в то время как отдельное действие является экземпляром класса, унаследованного от yii\base\Action или его потомков. Встроенные действия требуют меньше усилий для создания и в основном используются если у вас нет надобности в повторном использовании действий. Отдельные действия, с другой стороны, в основном создаются для использования в различных контроллерах или при использовании в расширениях.
Встроенные действия это те действия, которые определены в рамках методов контроллера, как мы это уже обсудили.
Названия методов действий могут быть получены из ID действий следующим образом:
action
.Например, index
соответствует actionIndex
, а hello-world
соответствует actionHelloWorld
.
Примечание: Названия имен действий являются регистрозависимыми. Если у вас есть метод
ActionIndex
, он не будет учтен как метод действия, таким образом, запрос к действиюindex
приведет к выбросу исключению. Также следует учесть, что методы действий должны иметь область видимости public. Методы имеющие область видимости private или protected НЕ определяют методы встроенных действий.
Встроенные действия в основном используются, потому что для их создания не нужного много усилий. Тем не менее, если вы планируете повторно использовать некоторые действия в различных местах, или если вы хотите перераспределить действия, вы должны определить его как отдельной действие.
Отдельные действия определяются в качестве классов, унаследованных от 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()
должен вернуть массив, ключами которого являются ID действий, а значениями - соответствующие
названия класса действия или конфигурация. В отличие от встроенных действий, ID отдельных действий могут
содержать произвольные символы, до тех пор пока они определены в методе actions()
.
Для создания отдельного действия, вы должны наследоваться от класса yii\base\Action или его потомков, и реализовать
метод run()
с областью видимости public. Роль метода run()
аналогична другим методам действий. Например,
<?php
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action
{
public function run()
{
return "Hello World";
}
}
Возвращаемое значение методов действий или метода run()
отдельного действия очень важно. Оно является результатом
выполнения соответствующего действия.
Возвращаемое значение может быть объектом response, который будет отослан конечному пользователю в качестве ответа.
В вышеприведенных примерах, все результаты действий являются строками, которые будут использованы в качестве тела ответа, высланного пользователю. Следующий пример, показывает действие может перенаправить браузер пользователя на новый URL, с помощью возврата response объекта (т. к. redirect() метод возвращает response объект):
public function actionForward()
{
// перенаправляем браузер пользователя на https://example.com
return $this->redirect('https://example.com');
}
Методы действий для встроенных действий и методы run()
для отдельных действий могут принимать параметры,
называемые параметры действий. Их значения берутся из запросов. Для Веб приложений,
значение каждого из параметров действия берется из $_GET
, используя название параметра в качестве ключа;
для консольных приложений, они соответствуют аргументам командной строки.
В приведенном ниже примере, действие view
(встроенное действие) определяет два параметра: $id
и $version
.
namespace app\controllers;
use yii\web\Controller;
class PostController extends Controller
{
public function actionView($id, $version = null)
{
// ...
}
}
Для разных запросов параметры действий будут определены следующим образом:
https://hostname/index.php?r=post/view&id=123
: параметр $id
будет присвоено значение '123'
, в то время
как $version
будет иметь значение null
, т. к. строка запроса не содержит параметра version
;https://hostname/index.php?r=post/view&id=123&version=2
: параметрам $id
и $version
будут присвоены
значения '123'
и '2'
соответственно;https://hostname/index.php?r=post/view
: будет брошено исключение yii\web\BadRequestHttpException, т. к.
обязательный параметр $id
не был указан в запросе;https://hostname/index.php?r=post/view&id[]=123
: будет брошено исключение yii\web\BadRequestHttpException, т. к.
параметр $id
получил неверное значение ['123']
.Если вы хотите, чтобы параметр действия принимал массив значений, вы должны использовать type-hint значение array
, как показано ниже:
public function actionView(array $id, $version = null)
{
// ...
}
Теперь, если запрос будет содержать URL https://hostname/index.php?r=post/view&id[]=123
, то параметр $id
примет значение
['123']
. Если запрос будет содержать URL https://hostname/index.php?r=post/view&id=123
, то параметр $id
все равно будет
содержать массив, т. к. скалярное значение '123'
будет автоматически сконвертировано в массив.
Вышеприведенные примеры в основном показывают как параметры действий работают для Веб приложений. Больше информации о параметрах консольных приложений представлено в секции Консольные команды.
Каждый контроллер имеет действие, указанное через свойство yii\base\Controller::$defaultAction. Когда маршрут содержит только ID контроллера, то подразумевается, что действие контроллера по умолчанию было запрошено.
По-умолчанию, это действие имеет значение index
. Если вы хотите изменить это значение, просто переопределите данное
свойство в классе контроллера следующим образом:
namespace app\controllers;
use yii\web\Controller;
class SiteController extends Controller
{
public $defaultAction = 'home';
public function actionHome()
{
return $this->render('home');
}
}
При обработке запроса, приложение создаст контроллер, основываясь на запрошенном маршруте. Для выполнения запроса, контроллер пройдет через следующие этапы жизненного цикла:
beforeAction()
приложения, модуля (если контроллер принадлежит модулю) и
самого контроллера.false
, то остальные, не вызванные методы beforeAction
будут пропущены, а выполнение
действия будет отменено;beforeAction()
вызовет событие beforeAction
, на которое вы можете назначить обработчики.afterAction
контроллера, модуля (если контроллер принадлежит модулю) и приложения.afterAction()
вызовет событие afterAction
, на которое вы можете назначить обработчики.В хорошо организованных приложениях контроллеры обычно очень тонкие и содержат лишь несколько строк кода. Если ваш контроллер слишком сложный, то обычно это означает, что вам надо провести его рефакторинг и перенести часть кода в другие места.
В целом, контроллеры
Found a typo or you think this page needs improvement?
Edit it on github !
Signup or Login in order to comment.