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 контролері яку буде викликано. Секція Маршрутизація містить більш детальну інформацію про те як маршрути співставляються з подіями.

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

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

<?php
namespace app\components;

use yii\base\Action;

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

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

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

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

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

В вищенаведених прикладах, всі результати подій є рядками, які будуть використані в якості тіла відповіді, висланого користувачеві. Наступний приклад, показує подію, що може перенаправити браузер користувача на новий URL, за допомогою повернення response об'єкта (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 події:
    • Якщо ID події не вказано, то буде використано yii\base\Controller::defaultAction;
    • Якщо ID події знайдено в yii\base\Controller::actions(), то буде створено окрему подію;
    • Якщо ID події відповідає методу події, то буде створено вбудовану подію;
    • В іншому випадку, буде вкинуте виключення yii\base\InvalidRouteException.
  3. Контролер послідовно викликає метод beforeAction() додатка, модуля (якщо контролер належить модулю) і самого контролера.
    • Якщо один із методів повернув false, то решта, невикликані методи beforeAction будуть пропущені, а виконання події буде відмінено;
    • За замовчуванням, кожний виклик метода beforeAction() викликає подію beforeAction, на яку ви можете призначити обробників.
  4. Контролер запускає подію:
    • Параметри події будуть проаналізовані і заповнені з даних запиту.
  5. Контролер послідовно викликає методи afterAction контролера, модуля (якщо контролер належить модулю) і додатка.
    • За замовчуванням, кожний виклик метода afterAction() викликає подію afterAction, на яку ви можете призначити обробників.
  6. Додаток, отримавши результат виконання події, присвоює його об’єкту response.

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

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

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

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