Yii2 framework backup
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

29 KiB

Контролери

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

У дії create (визначеній методом actionCreate()), код аналогічний. Він спочатку намагається завантажити модель за допомогою даних із запиту і зберегти модель. Якщо все пройшло успішно, то код перенаправить браузер на дію view із ID щойно створеної моделі. В іншому випадку - він відобразить предаставлення create, через яке користувач зможе вказати необхідні дані.

Маршрути

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

  • ID модуля: він існує, тільки якщо контролер належить не додатку, а модулю;
  • ID контролера: рядок, який унікально ідентифікує контролер серед всіх інших контролерів одного і того ж додатка (або одного й того ж модуля, якщо контролер належить модулю);
  • ID дії: рядок, який унікально ідентифікує дію серед всіх інших дій одного й того ж конторолера.

Маршрути можуть мати наступний формат:

ControllerID/ActionID

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

ModuleID/ControllerID/ActionID

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

Створення контролерів

У yii\web\Application контролери повинні бути успадкованими від класу yii\web\Controller або його нащадків. Аналогічно для yii\console\Application, контролери повинні бути успадкованими від класу yii\console\Controller або його нащадків. Наступний код визначає контролер site:

namespace app\controllers;

use yii\web\Controller;

class SiteController extends Controller
{
}

ID контролерів

За звичай контролер зроблений таким чином, що він повинен обробляти запити, які пов’язані з певним ресурсом. Саме з цієї причини, ID контролерів за завичай є іменниками, які посилаються на ресурс, який вони обробляють. Наприклад, ви можете використовувати article в якості ID контролера, який відповідає за обробку даних публікацій.

За замовчуванням, ID контролерів мають містити тільки наступні символи: англійські букви в нижньому регістрі, цифри, підкреслення, тире і слеш. Наприклад, обидва article та post-comment є прийнятними ID контролерів, в той час, як article?, PostComment, admin\post не є такими.

ID контролера також може містити префікс субдиректорії. Наприклад, у admin/article - частина article відповідає контролеру в субдиректорії admin yii\base\Application::controllerNamespace. Допустимими символами для префіксів субдиректорій є: англійські букви в нижньому і верхньому регістрах, цифри, символи підкреслення і слеш, де слеш - використовується в якості роздільника для багаторівневих субдиректорій (наприклад panels/admin).

Іменування класів контролерів

Назви класів контролерів можуть бути отримані із ID контролерів наступними правилами:

  • Привести у верхній регістр перший символ в кожному слові, розділеному дефісами. Зверніть увагу, що, якщо ID контролера містить слеш, то дане правило поширюється тільки на частину після останнього слеша в ID контролера.
  • Прибрати дефіси і замінити будь-який прямий слеш на зворотний.
  • Додати суфікс Controller.
  • Додати на початок yii\base\Application::controllerNamespace.

Нижче наведено декілька прикладів, з урахуванням того, що yii\base\Application::controllerNamespace має значення за замовчуванням 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/post2-comment має знаходитись у файлі @app/controllers/admin/Post2CommentController.php.

Інформація: Останній приклад admin/post2-comment показує яким чином ви можете розташувати контролер в директорії yii\base\Application::controllerNamespace. Це дуже зручно, коли ви хочете організувати свої контролери у декілька категорій і не хочете використовувати модулі.

Мапа контролерів

Ви можете налаштувати yii\base\Application::controllerMap для того, щоб подолати описані вище обмеження іменування ID контролерів і назв класів. В основному, це дуже зручно, коли ви використовуєте сторонні контролери, іменування яких ви не можете контролювати.

Ви можете налаштувати yii\base\Application::controllerMap в налаштуваннях додатка наступним чином:

[
    'controllerMap' => [
        // оголошує контролер "account", використовуючи назву класу
        'account' => 'app\controllers\UserController',

        // оголошує контролер "article", використовуючи масив конфігурації
        'article' => [
            'class' => 'app\controllers\PostController',
            'enableCsrfValidation' => false,
        ],
    ],
]

Контролер за замовчуванням

Кожний додаток має контролер за замовчуванням, вказаний через властивість yii\base\Application::defaultRoute. Коли в запиті не вказано маршрут, то буде використано маршрут із даної властивості. Для yii\web\Application, це значення рівне 'site', у той час, як для yii\console\Application, це 'help'. Таким чином, якщо вказаний URL http://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 дій

Частіше за все, дія розробляється для певної конкретної обробки ресурса. З цієї причини ID дій, в основному, є дієсловами, такими як view, update, і т.д.

За замовчуванням, ID дій повинні містити тільки такі символи: англійські букви в нижньому регістрі, цифри, підкреслення і дефіси. Дефіси в ID дій використовуються для поділу слів. Наприклад, view, update2, comment-post є допустимими ID дій, в той час, як view?, Update не є такими.

Ви можете створювати дії двома способами: вбудовані дії і окремі дії. Вбудована дія є методом, визначеним в класі контролера, тоді як окрема дія є екземпляром класу, успадкованого від yii\base\Action або його нащадків. Вбудовані дії вимагають менше зусиль для створення і, в основному, використовуються якщо у вас немає потреби у повторному використанні цих дій. Окремі дії, з іншого боку, в основному створюються для використання в різних контролерах або при використанні у розширеннях.

Вбудовані дії

Вбудовані дії це ті дії, які визначені у рамках методів контролера, як ми це вже обговорили.

Назви методів дій можуть бути отримані із ID дій наступним чином:

  • Привести перший символ кожного слова в 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 або його нащадків, і реалізувати публічний ("public") метод run(). Роль метода run() аналогічна іншим методам дій. Наприклад,

<?php
namespace app\components;

use yii\base\Action;

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

Результати дій

Значення, що повертається від метода дії або метода run() окремої дії дуже важливе. Воно є результатом виконання відповідної дії.

Значення, що повертається, може бути об’єктом відповіді, яке буде відправлено кінцевому користувачу.

  • Для yii\web\Application, значення, що повертається, також може бути довільними даними, яке буде призначене до yii\web\Response::data, а потім конвертоване у рядок, що представляє тіло відповіді.
  • Для yii\console\Application, значення, що повертається, також може бути числом, що представляє yii\console\Response::exitStatus виконання команди.

В вищенаведених прикладах всі результати дій є рядками, які будуть використані у якості тіла відповіді користувачу. Наступний приклад показує як дія може перенаправити браузер користувача на новий URL за допомогою повернення об’єкта відповіді (оскільки метод yii\web\Controller::redirect() повертає об’єкт response):

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

Параметри дій

Методи дій для вбудованих дій і методи run() для окремих дій можуть приймати, так звані, параметри дії. Їх значення беруться із запитів. Для yii\web\Application, значення кожного з параметрів дії береться із $_GET, використовуючи назву параметра у якості ключа; для yii\console\Application - вони відповідають аргументам командної строки.

В наступному прикладі, дія 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'].

Якщо ви хочете, щоб параметр дії приймав масив значень, ви повинні використати type-hint array параметра метода, як зображено нажче:

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

Тепер, якщо запит буде містити URL http://hostname/index.php?r=post/view&id[]=123, то параметр $id отримає значення ['123']. Якщо запит буде містити URL http://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');
    }
}

Життєвий цикл контролера

При обробці запиту, додаток створить контролер, базуючись на маршруті, який було запитано. Для виконання запиту, контролер пройде через наступні етапи життєвого циклу:

  1. Метод yii\base\Controller::init() буде викликаний після того, як контролер був створений і сконфігурований.
  2. Контролер створить об’єкт дії, базуючись на ID дії, яку було запитано:
  3. Контролер послідовно викликає метод beforeAction() додатка, модуля (якщо контролер належить модулю) і самого контролера.
    • Якщо один із методів повернув false, то решта невикликаних методів beforeAction будуть пропущені, а виконання дії буде відмінено;
    • За замовчуванням, кожний виклик метода beforeAction() викликає подію beforeAction, на яку ви можете призначити обробники.
  4. Контролер виконує дію:
    • Параметри дії будуть проаналізовані і заповнені із даних запиту.
  5. Контролер послідовно викликає методи afterAction контролера, модуля (якщо контролер належить модулю) і додатка.
    • За замовчуванням, кожний виклик метода afterAction() викликає подію afterAction, на яку ви можете призначити обробники.
  6. Додаток, отримавши результат виконання дії, привласнює його об’єкту response.

Кращі практики

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

В цілому, контролери

  • можуть мати доступ до даних запиту;
  • можуть викликати методи моделей та інших компонентів системи із даними запиту;
  • можуть використовувати представлення для формування відповіді;
  • не повинні займатись обробкою даних - це має відбуватися у моделях;
  • мають уникати використання HTML або іншої розмітки - краще це робити у представленнях.