Files
yii/docs/guide/ru/basics.controller.txt
2011-01-16 14:55:27 +00:00

315 lines
17 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
Контроллер
==========
`Контроллер (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>