mirror of
https://github.com/yiisoft/yii.git
synced 2026-03-04 15:24:07 +01:00
315 lines
17 KiB
Plaintext
315 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`.
|
||
|
||
> Note|Примечание: До версии 1.0.3 идентификатор контроллера указывался как
|
||
`path.to.xyz` вместо `path/to/xyz`.
|
||
|
||
Пользователь обращается к контроллеру и действию посредством маршрута (route).
|
||
Маршрут формируется путем объединения идентификаторов контроллера и действия,
|
||
отделенных косой чертой. Например, маршрут `post/edit` указывает на действие
|
||
`edit` контроллера `PostController` и, по умолчанию, URL `http://hostname/index.php?r=post/edit`
|
||
приведет к вызову именно этих контроллера и действия.
|
||
|
||
> Note|Примечание: По умолчанию маршруты чувствительны к регистру.
|
||
>Начиная с версии 1.0.1 это возможно изменить путем установки свойства
|
||
>[CUrlManager::caseSensitive в конфигурации приложения] равным false.
|
||
>В режиме нечувствительном к регистру убедитесь, что названия директорий,
|
||
>содержащих файлы классов контроллеров написаны в нижнем регистре, а также
|
||
>что [controller map|CWebApplication::controllerMap] и [action map|CController::actions]
|
||
>используют ключи в нижнем регистре.
|
||
|
||
|
||
Создание экземпляра контроллера
|
||
-------------------------------
|
||
Экземпляр контроллера создается, когда [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) (доступны, начиная с
|
||
версии 1.0.3), процесс описанный выше будет выглядеть несколько иначе. В частности,
|
||
приложение проверит, если идентификатор соответствует контроллеру внутри модуля.
|
||
В случае, если это имеет место, будет создан экземпляр модуля вместе с экземпляром
|
||
контроллера.
|
||
|
||
|
||
Действие
|
||
--------
|
||
Как было упомянуто выше, действие — это метод, имя которого начинается на `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.
|
||
|
||
|
||
Фильтры
|
||
---------------
|
||
Фильтр (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`. Если операторы `'+'` и `'-'` не указаны, фильтр будет
|
||
применен ко всем действиям.
|
||
|
||
<div class="revision">$Id: basics.controller.txt 2672 2010-11-22 19:13:16Z qiang.xue $</div> |