mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-05 15:54:07 +01:00
321 lines
17 KiB
Plaintext
321 lines
17 KiB
Plaintext
Контролер
|
||
=========
|
||
`Контролер (controller)` — це екземпляр класу [CController] або успадкованого від нього класу.
|
||
Він створюється обʼєктом додатку тоді, коли користувач робить відповідний запит.
|
||
При запуску контролер виконує відповідну дію, що зазвичай передбачає створення відповідних моделей
|
||
і рендеринг необхідних представлень.
|
||
У найпростішому випадку `дія` — це метод класу контролера, назва якого починається на `action`.
|
||
|
||
У контролера є дія за замовчуванням, яка виконується у випадку, коли користувач не вказує дію при запиті.
|
||
За замовчуванням ця дія називається `index`.
|
||
Змінити її можна шляхом встановлення значення [CController::defaultAction].
|
||
|
||
Наступний код визначає контролер `site` з діями `index` (за замовчуванням) та `contact`:
|
||
|
||
~~~
|
||
[php]
|
||
class SiteController extends CController
|
||
{
|
||
public function actionIndex()
|
||
{
|
||
// ...
|
||
}
|
||
|
||
public function actionContact()
|
||
{
|
||
// ...
|
||
}
|
||
}
|
||
~~~
|
||
|
||
|
||
Маршрут
|
||
-------
|
||
Контролери та дії розпізнаються по їхнім ідентифікаторам.
|
||
Ідентифікатор контролера — це запис формату `path/to/xyz`, що відповідає
|
||
файлу класу контролера `protected/controllers/path/to/XyzController.php`, де `xyz`
|
||
слід замінити реальною назвою класу (наприклад, `post` відповідає
|
||
`protected/controllers/PostController.php`). Ідентифікатор дії — це назва
|
||
методу без префікса `action`. Наприклад, якщо клас контролера містить метод
|
||
`actionEdit`, то ідентифікатор відповідної дії — `edit`.
|
||
|
||
Користувач звертається до контролера та дії за допомогою маршруту (route).
|
||
Маршрут формується шляхом обʼєднання ідентифікаторів контролера та дії, відокремлених символом `/`.
|
||
Наприклад, маршрут `post/edit` вказує на дію `edit` контролеру `PostController` і,
|
||
за замовчуванням, URL `http://hostname/index.php?r=post/edit` приведе до виклику саме цих контролера та дії.
|
||
|
||
> Note|Примітка: За замовчуванням маршрути чутливі до регістру.
|
||
>Це можливо змінити шляхом встановлення властивості
|
||
>[CUrlManager::caseSensitive] у конфігурації додатка рівною `false`.
|
||
>У режимі нечутливому до регістру переконайтеся, що назви директорій,
|
||
>які містять файли класів контролерів написані в нижньому регістрі, а також
|
||
>що [controller map|CWebApplication::controllerMap] та [action map|CController::actions]
|
||
>використовують ключі в нижньому регістрі.
|
||
|
||
Додаток може містити [модулі](/doc/guide/basics.module). Маршрут до дії
|
||
контролера всередині модуля задається у форматі `moduleID/controllerID/actionID`.
|
||
Більш детальніше це описано у [розділі про модулі](/doc/guide/basics.module).
|
||
|
||
Створення екземпляра контролера
|
||
-------------------------------
|
||
Екземпляр контролера створюється, коли [CWebApplication] обробляє вхідний запит.
|
||
Одержавши ідентифікатор контролера, додаток використовує наступні правила для
|
||
визначення класу контролера та його місцерозташування:
|
||
|
||
- якщо встановлена властивість [CWebApplication::catchAllRequest], контролер буде створений
|
||
на основі цієї властивості, а контролер, який запитує користувач, буде проігноровано.
|
||
Як правило, це використовується для встановлення додатка в режим технічного обслуговування
|
||
та відображення статичної сторінки з відповідним повідомленням;
|
||
|
||
- якщо ідентифікатор контролера виявлений у [CWebApplication::controllerMap], то для
|
||
створення екземпляру контролера буде використана відповідна конфігурація контролера;
|
||
|
||
- якщо ідентифікатор контролера відповідає формату `'path/to/xyz'`, то імʼя класу
|
||
контролера визначається як `XyzController`, а відповідний клас як
|
||
`protected/controllers/path/to/XyzController.php`.
|
||
Наприклад, ідентифікатор контролера `admin/user` відповідатиме класу
|
||
контролера — `Usercontroller` та файл `protected/controllers/admin/UserController.php`.
|
||
Якщо файл класу не існує, буде викликане виключення [CHttpException] з кодом помилки 404.
|
||
|
||
У випадку використання [модулів](/doc/guide/basics.module), процес, описаний вище, буде виглядати дещо інакше.
|
||
Зокрема, додаток перевірить, чи відповідає ідентифікатор контролеру всередині модуля.
|
||
Якщо відповідає — спочатку буде створений екземпляр модуля, потім екземпляр контролера.
|
||
|
||
|
||
Дія
|
||
--------
|
||
Як було згадано вище, дія — це метод, імʼя якого починається на `action`.
|
||
Ще один спосіб — створити клас дії та вказати контролеру створювати
|
||
екземпляр цього класу при необхідності. Такий підхід дозволяє використовувати
|
||
дії повторно.
|
||
|
||
|
||
Для створення класу дії необхідно виконати наступне:
|
||
|
||
~~~
|
||
[php]
|
||
class UpdateAction extends CAction
|
||
{
|
||
public function run()
|
||
{
|
||
// деяка логіка дії
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Щоб контролер знав про цю дію, необхідно перевизначити метод
|
||
[actions()|CController::actions] у класі контролера:
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
public function actions()
|
||
{
|
||
return array(
|
||
'edit'=>'application.controllers.post.UpdateAction',
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
У наведеному коді ми використовуємо псевдонім маршруту `application.controllers.post.UpdateAction`
|
||
щоб вказати на файл класу дії `protected/controllers/post/UpdateAction.php`.
|
||
Створюючи дії, засновані на класах, можна організувати додаток у модульному стилі.
|
||
Наприклад структура, директорій, приведена нижче, може бути використана для розташування коду контролерів:
|
||
~~~
|
||
protected/
|
||
controllers/
|
||
PostController.php
|
||
UserController.php
|
||
post/
|
||
CreateAction.php
|
||
ReadAction.php
|
||
UpdateAction.php
|
||
user/
|
||
CreateAction.php
|
||
ListAction.php
|
||
ProfileAction.php
|
||
UpdateAction.php
|
||
~~~
|
||
|
||
### Привʼязка параметрів дій
|
||
|
||
Починаючи з версії 1.1.4, в Yii зʼявилася підтримка автоматичної привʼязки
|
||
параметрів для дії контролера. Тобто можна задати іменовані параметри,
|
||
в які автоматично будуть потрапляти відповідні значення із `$_GET`.
|
||
|
||
Для того, щоб показати, як це працює, припустимо, що нам потрібно
|
||
реалізувати дію `create` контролера `PostController`. Дія вимагає двох параметрів:
|
||
|
||
* `category`: ID категорії, у якій буде створюватись запис. Ціле число;
|
||
* `language`: рядок, який містить код мови, яка буде використовуватися у запису.
|
||
|
||
Скоріш за все у результаті для отримання параметрів із `$_GET` у нас вийде
|
||
наведений нижче нудний код:
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
public function actionCreate()
|
||
{
|
||
if(isset($_GET['category']))
|
||
$category=(int)$_GET['category'];
|
||
else
|
||
throw new CHttpException(404,'Невірний запит');
|
||
|
||
if(isset($_GET['language']))
|
||
$language=$_GET['language'];
|
||
else
|
||
$language='en';
|
||
|
||
// … дійсно корисна частина коду …
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Тепер, використовуючи параметри дій, ми можемо отримати більш охайний код:
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
public function actionCreate($category, $language='en')
|
||
{
|
||
$category=(int)$category;
|
||
|
||
// … дійсно корисна частина коду …
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Ми додаємо два параметри методу `actionCreate`. Імʼя кожного повинно в точності
|
||
співпадати з одним із ключів у `$_GET`. Параметру `$language` задано значення
|
||
за замовчуванням `en`, яке використовується тоді, коли у запиті відповідний параметр
|
||
відсутній. Так як `$category` не має значення за замовчуванням, у випадку
|
||
відсутності відповідного параметру у запиті буде автоматично викликане виключення
|
||
[CHttpException] (із кодом помилки 400).
|
||
|
||
Починаючи із версії 1.1.5, Yii підтримує масиви як параметри дій.
|
||
Використовувати їх можна наступним чином:
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
public function actionCreate(array $categories)
|
||
{
|
||
// Yii приведе $categories до масиву
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Ми додаємо ключове слово `array` перед параметром `$categories`.
|
||
Після цього, якщо параметр `$_GET['categories']` є простим рядком, то він буде
|
||
приведений до масиву, який міститиме вихідний рядок.
|
||
|
||
> Note|Примітка: Якщо параметр оголошений без вказівки типу `array`, то він повинен
|
||
> бути скалярним (тобто не масивом). У цьому випадку передача масива через
|
||
> `$_GET`-параметр приведе до виключення HTTP.
|
||
|
||
|
||
Починаючи із версії 1.1.7, автоматична привʼязка параметрів працює і з
|
||
діями, оформленими як класи. Якщо метод `run()` у класі дії
|
||
описати з параметрами, то ці параметри заповнюються відповідними значеннями
|
||
із HTTP-запиту:
|
||
|
||
~~~
|
||
[php]
|
||
class UpdateAction extends CAction
|
||
{
|
||
public function run($id)
|
||
{
|
||
// $id буде заповнений значенням із $_GET['id']
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Фільтри
|
||
---------------
|
||
Фільтр (filter) – це частина коду, що може виконуватися до або після
|
||
виконання дії контролера залежно від конфігурації. Наприклад, фільтр
|
||
контролю доступу може перевіряти, чи аутентифікований користувач перед тим,
|
||
як буде виконана запитана дія. Фільтр, що контролює продуктивність додатку,
|
||
може бути використаний для визначення часу, витраченого на виконання дії.
|
||
|
||
Дія може мати безліч фільтрів. Фільтри запускаються в такому порядку, як
|
||
вони зазначені в списку фільтрів, при цьому фільтр може запобігти виконанню
|
||
дії і наступних за ним фільтрів.
|
||
|
||
Фільтр може бути визначений як метод класу контролера. Імʼя методу повинне починатися на `filter`.
|
||
Наприклад, метод `filterAccessControl` визначає фільтр `accessControl`.
|
||
Метод фільтру оформлюється у такий спосіб:
|
||
|
||
~~~
|
||
[php]
|
||
public function filterAccessControl($filterchain)
|
||
{
|
||
// для виконання наступних фільтрів і виконання дії викличте метод $filterchain->run()
|
||
}
|
||
~~~
|
||
|
||
де `$filterChain` — екземпляр класу [CFilterChain], який являє собою список фільтрів,
|
||
асоційованих із запитаною дією. У коді фільтра можна викликати
|
||
`$filterChain->run()` для того, щоб продовжити виконання наступних фільтрів і дії.
|
||
|
||
Фільтр також може бути екземпляром класу [CFilter] або похідного від нього.
|
||
Наступний код визначає новий клас фільтра:
|
||
|
||
~~~
|
||
[php]
|
||
class PerformanceFilter extends CFilter
|
||
{
|
||
protected function preFilter($filterChain)
|
||
{
|
||
// код, виконуваний до виконання дії
|
||
return true; // false — для випадку, коли дія не повинна бути виконана
|
||
}
|
||
|
||
protected function postFilter($filterChain)
|
||
{
|
||
// код, виконуваний після виконання дії
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Для того, щоб застосувати фільтр до дії, необхідно перевизначити метод
|
||
`CController::filters()`, який повертає масив конфігурацій фільтрів. Наприклад:
|
||
|
||
~~~
|
||
[php]
|
||
class PostController extends CController
|
||
{
|
||
…
|
||
public function filters()
|
||
{
|
||
return array(
|
||
'postOnly + edit, create',
|
||
array(
|
||
'application.filters.PerformanceFilter - edit, create',
|
||
'unit'=>'second',
|
||
),
|
||
);
|
||
}
|
||
}
|
||
~~~
|
||
|
||
Даний код визначає два фільтри: `postOnly` і `PerformanceFilter`.
|
||
Фільтр `postOnly` заданий як метод (відповідний метод уже визначений в
|
||
[CController]), в той час як `PerformanceFilter` — фільтр на базі класу.
|
||
Псевдонім `application.filters.PerformanceFilter` вказує на файл класу фільтра —
|
||
`protected/filters/PerformanceFilter`. Для конфігурації `PerformanceFilter`
|
||
використаний масив, тому можливо ініціалізувати значення властивості фільтру.
|
||
У цьому випадку властивість `unit` фільтра `PerformanceFilter` буде
|
||
ініціалізовано значенням `'second'`.
|
||
|
||
Використовуючи оператори `'+'` і `'-'` можна вказати, до яких дій повинен чи
|
||
не повинен бути застосованим фільтр. У наведеному прикладі `postOnly` повинен бути
|
||
застосований до дій `edit` та `create`, а `PerformanceFilter` — до всіх дій,
|
||
окрім `edit` і `create`. Якщо оператори `'+'` і `'-'` не зазначені, фільтр буде
|
||
застосований до всіх дій. |