Контролери є частиною архітектури 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 https://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
).
Назви класів контролерів можуть бути отримані із ідентифікаторів контролерів наступним чином:
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
.
Info: Останній приклад
admin/post-comment
показує яким чином ви можете розташувати контролер в під-директорії простору імен контролера. Це дуже зручно, коли ви хочете організувати свої контролери у декілька категорій і не хочете використовувати модулі.
Ви можете налаштувати мапу контролерів для того, щоб подолати описані вище обмеження іменування ідентифікаторів контролерів і назв класів. В основному, це дуже зручно, коли ви використовуєте сторонні контролери, іменування яких ви не можете контролювати.
Ви можете налаштувати мапу контролерів в налаштуваннях додатка наступним чином:
[
'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',
]
Створення дій може бути настільки ж простим, як і оголошення так званих методів дій у класі контролера. Метод дії це
публічний метод, ім’я якого починається зі слова 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 або його нащадків. Вбудовані дії вимагають менше зусиль для створення і, в основному, використовуються якщо у вас немає потреби у повторному використанні цих дій. Автономні дії, з іншого боку, в основному створюються для використання в різних контролерах або для розподілення у вигляді розширень.
Вбудовані дії це ті дії, які визначені у рамках методів контролера, як це було щойно описано.
Назви методів дій можуть бути отримані із ідентифікаторів дій наступним чином:
action
.Наприклад, index
перетвориться у actionIndex
, а hello-world
перетвориться у actionHelloWorld
.
Note: Назви імен методів дій є регістр-залежними. Якщо у вас є метод
ActionIndex
, то його не буде враховано як метод дії, і в результаті, запит до діїindex
призведе до отримання виключення. Також слід врахувати, що методи дій повинні бути публічними ("public"). Приватні ("private") або захищені ("protected") методи НЕ визначають вбудованих дій.
В основному використовуються вбудовані дії, оскільки для їх створення не потрібного багато зусиль. Тим не менше, якщо ви плануєте повторно використовувати деякі дії у різних місцях або якщо ви хочете перерозподілити дії, ви повинні визначити їх як автономні дії.
Автономні дії визначаються в якості класів, успадкованих від yii\base\Action або його нащадків. Наприклад, в релізах Yii присутні yii\web\ViewAction та yii\web\ErrorAction, обидва класи є окремими діями.
Для використання автономної дії, ви маєте вказати її у мапі дій за допомогою перевизначення методу actions() у вашому класі контролера, наступним чином:
public function actions()
{
return [
// оголошує дію "error" за допомогою назви класу
'error' => 'yii\web\ErrorAction',
// оголошує дію "view" за допомогою конфігураційного масиву
'view' => [
'class' => 'yii\web\ViewAction',
'viewPrefix' => '',
],
];
}
Як ви можете бачити, метод actions()
повинен повернути масив, ключами якого є ідентифікатори дій, а значеннями - відповідні
назви класів дій або конфігурації. На відміну від вбудованих дій, ідентифікатори автономних дій
можуть містити довільні символи, доки вони визначені у методі actions()
.
Для створення класу автономної дії, ви повинні успадкуватись від класу yii\base\Action або його нащадків, і реалізувати публічний ("public") метод run(). Роль метода run() аналогічна іншим методам дій. Наприклад,
<?php
namespace app\components;
use yii\base\Action;
class HelloWorldAction extends Action
{
public function run()
{
return "Hello World";
}
}
Значення, що повертається від методу дії або методу run() автономної дії дуже важливе. Воно є результатом виконання відповідної дії.
Значення, що повертається, може бути об’єктом відповіді, яке буде відправлено кінцевому користувачу.
У вищенаведених прикладах всі результати дій є текстовими рядками, які будуть використані у якості тіла відповіді для відправлення кінцевому користувачу. Наступний приклад показує як дія може перенаправити браузер користувача на новий URL за допомогою повернення об’єкта відповіді (оскільки метод 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']
.Якщо ви хочете, щоб параметр дії приймав масив значень, ви повинні вказати тип 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. Коли маршрут містить тільки ідентифікатор контролера, то розуміється, що було запитана дія контролера за замовчуванням.
За замовчуванням, ця дія має значення 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
, на яку ви можете призначити обробник.В добре організованому додатку контролери, зазвичай дуже малі, з діями, що містять лише декілька рядків коду. Якщо ваш контролер дуже складний, це зазвичай означає, що вам потрібно провести його рефакторинг і перенести деякий код в інші класи.
В цілому, контролери