mirror of
				https://github.com/yiisoft/yii2.git
				synced 2025-10-31 18:47:33 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			437 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			437 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
| Kontrolyor
 | ||
| ===========
 | ||
| 
 | ||
| Kontrolyor [MVC](https://ru.wikipedia.org/wiki/Model-View-Controller) arxitekturasining bir qismi hisoblanadi. Bu [[yii\base\Controller]] klassidan voris qilib yaratilgan klass obyektlaridir, ushbu obyektlar so'rovlarni (request) qayta ishlash va javoblarni (response) tayyorlash uchun mo'ljallangan. [Ilova (application)](structure-applications.md) so'rovlarni qayta ishlagandan so'ng, so'rovlarga mos kontrolyor obyektlarini yaratadi va bu obyektlar kiruvchi ma'lumotlarni tahlil qiladi hamda ushbu ma'lumotlarni [model](structure-models.md)ga jo'natadi so'ng modeldan olingan natijalarni [namoyish (view)](structure-views.md)ga joylashtiradi va oxirgi natijani hosil qiladi.
 | ||
| 
 | ||
| ## Amallar <span id="actions"></span>
 | ||
| 
 | ||
| Kontrolyorlar *amallar (action)*dan tashkil topadi, *amallar* asosiy bloklar hisoblanib, foydalanuvchilar amallarga murojaat qilishi mumkin va ma'lum buyruqlar bajarilib natija hosil qilinadi hamda natija foydalanuvchiga qaytariladi. Bitta kontrolyorda bitta va undan ortiq amal bo'lishi mumkin.
 | ||
| 
 | ||
| Quyidagi misolda ikkita amaldan (`view` va `create`) tashkil topgan `post` kontrolyori keltirilgan:
 | ||
| 
 | ||
| ```php
 | ||
| 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()`), код сначала загружает [модель](structure-models.md)
 | ||
| согласно запрошенному ID модели; Если модель успешно загружена, то код отобразит ее с помощью [представления](structure-views.md)
 | ||
| под названием `view`. В противном случае будет брошено исключение.
 | ||
| 
 | ||
| В действии `create` (определенном методом `actionCreate()`), код аналогичен. Он сначала пытается загрузить [модель](structure-models.md)
 | ||
| с помощью данных из запроса и сохранить модель. Если все прошло успешно, то код перенаправляет браузер на действие `view` с ID только
 | ||
| что созданной модели. В противном случае он отобразит представление `create`, через которое пользователь может заполнить нужные данные.
 | ||
| 
 | ||
| 
 | ||
| ## Маршруты <span id="routes"></span>
 | ||
| 
 | ||
| Конечные пользователи обращаются к действиям через так называемые *маршруты*. Маршрут это строка, состоящая из следующих частей:
 | ||
| 
 | ||
| * ID модуля: он существует, только если контроллер принадлежит не приложению, а [модулю](structure-modules.md);
 | ||
| * ID контроллера: строка, которая уникально идентифицирует контроллер среди всех других контроллеров одного и того же приложения
 | ||
|   (или одного и того же модуля, если контроллер принадлежит модулю);
 | ||
| * ID действия: строка, которая уникально идентифицирует действие среди всех других действия одного и того же контроллера.
 | ||
| 
 | ||
| Маршруты могут иметь следующий формат:
 | ||
| 
 | ||
| ```
 | ||
| ControllerID/ActionID
 | ||
| ```
 | ||
| 
 | ||
| или следующий формат, если контроллер принадлежит модулю:
 | ||
| 
 | ||
| ```php
 | ||
| ModuleID/ControllerID/ActionID
 | ||
| ```
 | ||
| 
 | ||
| Таким образом, если пользователь запрашивает URL `https://hostname/index.php?r=site/index`, то `index` действие в `site` контроллере будет вызвано.
 | ||
| Секция [Маршрутизация](runtime-routing.md) содержит более подробную информацию о том как маршруты сопоставляются с действиями.
 | ||
| 
 | ||
| 
 | ||
| ## Создание контроллеров <span id="creating-controllers"></span>
 | ||
| 
 | ||
| В [[yii\web\Application|Веб приложениях]], контроллеры должны быть унаследованы от [[yii\web\Controller]] или его потомков.
 | ||
| Аналогично для [[yii\console\Application|консольных приложений]], контроллеры должны быть унаследованы от [[yii\console\Controller]] или
 | ||
| его потомков. Следующий код определяет `site` контроллер:
 | ||
| 
 | ||
| ```php
 | ||
| namespace app\controllers;
 | ||
| 
 | ||
| use yii\web\Controller;
 | ||
| 
 | ||
| class SiteController extends Controller
 | ||
| {
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### ID контроллеров <span id="controller-ids"></span>
 | ||
| 
 | ||
| Обычно контроллер сделан таким образом, что он должен обрабатывать запросы, связанные с определенным ресурсом.
 | ||
| Именно по этим причинам, ID контроллеров обычно являются существительные, ссылающиеся на ресурс, который они обрабатывают.
 | ||
| Например, вы можете использовать `article` в качестве ID контроллера, которые отвечает за обработку данных статей.
 | ||
| 
 | ||
| По-умолчанию, ID контроллеров должны содержать только следующие символы: Английские буквы в нижнем регистре, цифры, подчеркивания,
 | ||
| тире и слэш. Например, оба `article` и `post-comment` являются допустимыми ID контроллеров, в то время как `article?`, `PostComment`,
 | ||
| `admin\post` не являются таковыми.
 | ||
| 
 | ||
| ID контроллеров также могут содержать префикс подпапки. Например, в `admin/article` часть `article` является контроллером в 
 | ||
| подпапке `admin` в [[yii\base\Application::controllerNamespace|пространстве имен контроллеров]].
 | ||
| Допустимыми символами для префиксов подпапок являются: Английские буквы в нижнем  и верхнем регистре, символы подчеркивания и
 | ||
| слэш, где слэш используется в качестве разграничителя для многовложенных подпапок (например `panels/admin`).
 | ||
| 
 | ||
| 
 | ||
| 
 | ||
| ### Правила наименования классов контроллеров <span id="controller-class-naming"></span>
 | ||
| 
 | ||
| Названия классов контроллеров могут быть получены из 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`.
 | ||
| 
 | ||
| Классы контроллеров должны быть [автозагружаемыми](concept-autoloading.md). Именно по этой причине, в вышеприведенном примере,
 | ||
| контроллер `article` должен быть сохранен в файл, [псевдоним](concept-aliases.md) которого `@app/controllers/ArticleController.php`;
 | ||
| в то время как контроллер `admin/post-comment` должен находиться в файле `@app/controllers/admin/PostCommentController.php`.
 | ||
| 
 | ||
| > Информация: Последний пример `admin/post-comment` показывает каким образом вы можете расположить контроллер в подпапке
 | ||
|   [[yii\base\Application::controllerNamespace|пространства имен контроллеров]]. Это очень удобно, когда вы хотите организовать свои контроллеры
 | ||
|   в несколько категорий и не хотите использовать [модули](structure-modules.md).
 | ||
| 
 | ||
| 
 | ||
| ### Карта контроллеров <span id="controller-map"></span>
 | ||
| 
 | ||
| Вы можете сконфигурировать [[yii\base\Application::controllerMap|карту контроллеров]] для того, чтобы преодолеть
 | ||
| описанные выше ограничения именования ID контроллеров и названий классов. В основном это очень удобно, когда вы используете
 | ||
| сторонние контроллеры, именование которых вы не можете контролировать.
 | ||
| 
 | ||
| Вы можете сконфигурировать [[yii\base\Application::controllerMap|карту контроллеров]] в [настройках приложения](structure-applications.md#application-configurations)
 | ||
| следующим образом:
 | ||
| 
 | ||
| ```php
 | ||
| [
 | ||
|     'controllerMap' => [
 | ||
|         [
 | ||
|             // объявляет "account" контроллер, используя название класса
 | ||
|             'account' => 'app\controllers\UserController',
 | ||
| 
 | ||
|             // объявляет "article" контроллер, используя массив конфигурации
 | ||
|             'article' => [
 | ||
|                 'class' => 'app\controllers\PostController',
 | ||
|                 'enableCsrfValidation' => false,
 | ||
|             ],
 | ||
|         ],
 | ||
|     ],
 | ||
| ]
 | ||
| ```
 | ||
| 
 | ||
| ### Контроллер по умолчанию <span id="default-controller"></span>
 | ||
| 
 | ||
| Каждое приложение имеет контроллер по умолчанию, указанный через свойство [[yii\base\Application::defaultRoute]].
 | ||
| Когда в запросе не указан [маршрут](#routes), тогда будет использован маршрут указанный в данном свойстве.
 | ||
| Для [[yii\web\Application|Веб приложений]], это значение `'site'`, в то время как для [[yii\console\Application|консольных приложений]],
 | ||
| это `'help'`. Таким образом, если задан URL `https://hostname/index.php`, это означает, что контроллер `site` выполнит обработку запроса.
 | ||
| 
 | ||
| Вы можете изменить контроллер по умолчанию следующим образом в [настройках приложения](structure-applications.md#application-configurations):
 | ||
| 
 | ||
| ```php
 | ||
| [
 | ||
|     'defaultRoute' => 'main',
 | ||
| ]
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ## Создание действий <span id="creating-actions"></span>
 | ||
| 
 | ||
| Создание действий не представляет сложностей также как и объявление так называемых *методов действий* в классе контроллера. Метод действия
 | ||
| это *public* метод, имя которого начинается со слова `action`. Возвращаемое значение метода действия представляет собой ответные данные,
 | ||
| которые будут высланы конечному пользователю. Приведенный ниже код определяет два действия `index` и `hello-world`:
 | ||
| 
 | ||
| ```php
 | ||
| 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 действий <span id="action-ids"></span>
 | ||
| 
 | ||
| В основном действие разрабатывается для какой-либо конкретной обработки ресурса. По этой причине, ID действий в основном
 | ||
| являются глаголами, такими как `view`, `update`, и т. д.
 | ||
| 
 | ||
| По-умолчанию, ID действия должен содержать только следующие символы: Английские буквы в нижнем регистре, цифры,
 | ||
| подчеркивания и дефисы. Дефисы в ID действий используются для разделения слов. Например, `view`, `update2`, `comment-post` являются
 | ||
| допустимыми ID действий, в то время как `view?`, `Update` не являются таковыми.
 | ||
| 
 | ||
| Вы можете создавать действия двумя способами: встроенные действия и отдельные действия. Встроенное действие является методом, определенным
 | ||
| в классе контроллера, в то время как отдельное действие является экземпляром класса, унаследованного от [[yii\base\Action]] или его потомков.
 | ||
| Встроенные действия требуют меньше усилий для создания и в основном используются если у вас нет надобности в повторном использовании действий.
 | ||
| Отдельные действия, с другой стороны, в основном создаются для использования в различных контроллерах или при использовании в [расширениях](structure-extensions.md).
 | ||
| 
 | ||
| 
 | ||
| ### Встроенные действия <span id="inline-actions"></span>
 | ||
| 
 | ||
| Встроенные действия это те действия, которые определены в рамках методов контроллера, как мы это уже обсудили.
 | ||
| 
 | ||
| Названия методов действий могут быть получены из ID действий следующим образом:
 | ||
| 
 | ||
| * Привести первый символ каждого слова в ID действия в верхний регистр;
 | ||
| * Убрать дефисы;
 | ||
| * Добавить префикс `action`.
 | ||
| 
 | ||
| Например, `index` соответствует `actionIndex`, а `hello-world` соответствует `actionHelloWorld`.
 | ||
| 
 | ||
| > Примечание: Названия имен действий являются *регистрозависимыми*. Если у вас есть метод `ActionIndex`, он не будет
 | ||
|   учтен как метод действия, таким образом, запрос к действию `index` приведет к выбросу исключению. Также следует учесть, что методы действий
 | ||
|   должны иметь область видимости public. Методы имеющие область видимости private или protected НЕ определяют методы встроенных действий.
 | ||
| 
 | ||
| 
 | ||
| Встроенные действия в основном используются, потому что для их создания не нужного много усилий. Тем не менее, если вы планируете повторно
 | ||
| использовать некоторые действия в различных местах, или если вы хотите перераспределить действия, вы должны определить его как *отдельной действие*.
 | ||
| 
 | ||
| 
 | ||
| ### Отдельные действия <span id="standalone-actions"></span>
 | ||
| 
 | ||
| Отдельные действия определяются в качестве классов, унаследованных от [[yii\base\Action]] или его потомков.
 | ||
| Например, в Yii релизах, присутствуют [[yii\web\ViewAction]] и [[yii\web\ErrorAction]], оба из которых являются
 | ||
| отдельными действиями.
 | ||
| 
 | ||
| Для использования отдельного действия, вы должны указать его в *карте действий*, с помощью переопределения метода
 | ||
| [[yii\base\Controller::actions()]] в вашем классе контроллера, следующим образом:
 | ||
| 
 | ||
| ```php
 | ||
| public function actions()
 | ||
| {
 | ||
|     return [
 | ||
|         // объявляет "error" действие с помощью названия класса
 | ||
|         'error' => 'yii\web\ErrorAction',
 | ||
| 
 | ||
|         // объявляет "view" действие с помощью конфигурационного массива
 | ||
|         'view' => [
 | ||
|             'class' => 'yii\web\ViewAction',
 | ||
|             'viewPrefix' => '',
 | ||
|         ],
 | ||
|     ];
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| Как вы можете видеть, метод `actions()` должен вернуть массив, ключами которого являются ID действий, а значениями - соответствующие
 | ||
| названия класса действия или [конфигурация](concept-configurations.md). В отличие от встроенных действий, ID отдельных действий могут
 | ||
| содержать произвольные символы, до тех пор пока они определены в методе `actions()`.
 | ||
| 
 | ||
| Для создания отдельного действия, вы должны наследоваться от класса [[yii\base\Action]] или его потомков, и реализовать
 | ||
| метод `run()` с областью видимости public. Роль метода `run()` аналогична другим методам действий. Например,
 | ||
| 
 | ||
| ```php
 | ||
| <?php
 | ||
| namespace app\components;
 | ||
| 
 | ||
| use yii\base\Action;
 | ||
| 
 | ||
| class HelloWorldAction extends Action
 | ||
| {
 | ||
|     public function run()
 | ||
|     {
 | ||
|         return "Hello World";
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Результаты действий <span id="action-results"></span>
 | ||
| 
 | ||
| Возвращаемое значение методов действий или метода `run()` отдельного действия очень важно. Оно является результатом
 | ||
| выполнения соответствующего действия.
 | ||
| 
 | ||
| Возвращаемое значение может быть объектом [response](runtime-responses.md), который будет отослан конечному пользователю 
 | ||
| в качестве ответа.
 | ||
| 
 | ||
| * Для [[yii\web\Application|Веб приложений]], возвращаемое значение также может быть произвольными данными, которые будут
 | ||
|   присвоены [[yii\web\Response::data]], а затем сконвертированы в строку, представляющую тело ответа.
 | ||
| * Для [[yii\console\Application|Консольных приложений]], возвращаемое значение также может быть числом, представляющим
 | ||
|   [[yii\console\Response::exitStatus|статус выхода]] исполнения команды.
 | ||
| 
 | ||
| В вышеприведенных примерах, все результаты действий являются строками, которые будут использованы в качестве тела ответа,
 | ||
| высланного пользователю. Следующий пример, показывает действие может перенаправить браузер пользователя на новый URL, с помощью
 | ||
| возврата response объекта (т. к. [[yii\web\Controller::redirect()|redirect()]] метод возвращает response объект):
 | ||
| 
 | ||
| ```php
 | ||
| public function actionForward()
 | ||
| {
 | ||
|     // перенаправляем браузер пользователя на https://example.com
 | ||
|     return $this->redirect('https://example.com');
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ### Параметры действий <span id="action-parameters"></span>
 | ||
| 
 | ||
| Методы действий для встроенных действий и методы `run()` для отдельных действий могут принимать параметры,
 | ||
| называемые *параметры действий*. Их значения берутся из запросов. Для [[yii\web\Application|Веб приложений]],
 | ||
| значение каждого из параметров действия берется из `$_GET`, используя название параметра в качестве ключа;
 | ||
| для [[yii\console\Application|консольных приложений]], они соответствуют аргументам командной строки.
 | ||
| 
 | ||
| В приведенном ниже примере, действие `view` (встроенное действие) определяет два параметра: `$id` и `$version`.
 | ||
| 
 | ||
| ```php
 | ||
| namespace app\controllers;
 | ||
| 
 | ||
| use yii\web\Controller;
 | ||
| 
 | ||
| class PostController extends Controller
 | ||
| {
 | ||
|     public function actionView($id, $version = null)
 | ||
|     {
 | ||
|         // ...
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| Для разных запросов параметры действий будут определены следующим образом:
 | ||
| 
 | ||
| * `https://hostname/index.php?r=post/view&id=123`: параметр `$id` будет присвоено значение `'123'`, в то время
 | ||
|   как `$version` будет иметь значение `null`, т. к. строка запроса не содержит параметра `version`;
 | ||
| * `https://hostname/index.php?r=post/view&id=123&version=2`: параметрам `$id` и `$version` будут присвоены
 | ||
|   значения `'123'` и `'2'` соответственно;
 | ||
| * `https://hostname/index.php?r=post/view`: будет брошено исключение [[yii\web\BadRequestHttpException]], т. к.
 | ||
|   обязательный параметр `$id` не был указан в запросе;
 | ||
| * `https://hostname/index.php?r=post/view&id[]=123`: будет брошено исключение [[yii\web\BadRequestHttpException]], т. к.
 | ||
|   параметр `$id` получил неверное значение `['123']`.
 | ||
| 
 | ||
| Если вы хотите, чтобы параметр действия принимал массив значений, вы должны использовать type-hint значение `array`, как показано ниже:
 | ||
| 
 | ||
| ```php
 | ||
| public function actionView(array $id, $version = null)
 | ||
| {
 | ||
|     // ...
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| Теперь, если запрос будет содержать URL `https://hostname/index.php?r=post/view&id[]=123`, то параметр `$id` примет значение
 | ||
| `['123']`. Если запрос будет содержать URL `https://hostname/index.php?r=post/view&id=123`, то параметр `$id` все равно будет
 | ||
| содержать массив, т. к. скалярное значение `'123'` будет автоматически сконвертировано в массив.
 | ||
| 
 | ||
| Вышеприведенные примеры в основном показывают как параметры действий работают для Веб приложений. Больше информации
 | ||
| о параметрах консольных приложений представлено в секции [Консольные команды](tutorial-console.md).
 | ||
| 
 | ||
| 
 | ||
| ### Действие по умолчанию <span id="default-action"></span>
 | ||
| 
 | ||
| Каждый контроллер имеет действие, указанное через свойство [[yii\base\Controller::defaultAction]].
 | ||
| Когда [маршрут](#routes) содержит только ID контроллера, то подразумевается, что действие контроллера по умолчанию
 | ||
| было запрошено.
 | ||
| 
 | ||
| По-умолчанию, это действие имеет значение `index`. Если вы хотите изменить это значение, просто переопределите данное
 | ||
| свойство в классе контроллера следующим образом:
 | ||
| 
 | ||
| ```php
 | ||
| namespace app\controllers;
 | ||
| 
 | ||
| use yii\web\Controller;
 | ||
| 
 | ||
| class SiteController extends Controller
 | ||
| {
 | ||
|     public $defaultAction = 'home';
 | ||
| 
 | ||
|     public function actionHome()
 | ||
|     {
 | ||
|         return $this->render('home');
 | ||
|     }
 | ||
| }
 | ||
| ```
 | ||
| 
 | ||
| 
 | ||
| ## Жизненный цикл контроллера <span id="controller-lifecycle"></span>
 | ||
| 
 | ||
| При обработке запроса, [приложение](structure-applications.md) создаст контроллер, основываясь на 
 | ||
| запрошенном [маршруте](#routes). Для выполнения запроса, контроллер пройдет через следующие этапы
 | ||
| жизненного цикла:
 | ||
| 
 | ||
| 1. Метод [[yii\base\Controller::init()]] будет вызван после того как контроллер будет создан и сконфигурирован;
 | ||
| 2. Контроллер создает объект действия, основываясь на запрошенном ID действия:
 | ||
|    * Если ID действия не указан, то будет использовано [[yii\base\Controller::defaultAction|ID действия по умолчанию]];
 | ||
|    * Если ID действия найдено в [[yii\base\Controller::actions()|карте действий]], то отдельное действие будет создано;
 | ||
|    * Если ID действия соответствует методу действия, то встроенное действие будет создано;
 | ||
|    * В противном случае, будет выброшено исключение [[yii\base\InvalidRouteException]].
 | ||
| 3. Контроллер последовательно вызывает метод `beforeAction()` приложения, модуля (если контроллер принадлежит модулю) и
 | ||
|    самого контроллера.
 | ||
|    * Если один из методов вернул `false`, то остальные, не вызванные методы `beforeAction` будут пропущены, а выполнение
 | ||
|      действия будет отменено;
 | ||
|    * По-умолчанию, каждый вызов метода `beforeAction()` вызовет событие `beforeAction`, на которое вы можете назначить обработчики.
 | ||
| 4. Контроллер запускает действие:
 | ||
|    * Параметры действия будут проанализированы и заполнены из данных запроса.
 | ||
| 5. Контроллер последовательно вызывает методы `afterAction` контроллера, модуля (если контроллер принадлежит модулю) и приложения.
 | ||
|    * По-умолчанию, каждый вызов метода `afterAction()` вызовет событие `afterAction`, на которое вы можете назначить обработчики.
 | ||
| 6. Приложение, получив результат выполнения действия, присвоит его объекту [response](runtime-responses.md).
 | ||
| 
 | ||
| 
 | ||
| ## Лучшие практики <span id="best-practices"></span>
 | ||
| 
 | ||
| В хорошо организованных приложениях контроллеры обычно очень тонкие и содержат лишь несколько строк кода.
 | ||
| Если ваш контроллер слишком сложный, то обычно это означает, что вам надо провести его рефакторинг и перенести часть кода
 | ||
| в другие места.
 | ||
| 
 | ||
| В целом, контроллеры
 | ||
| 
 | ||
| * могут иметь доступ к данным [запроса](runtime-requests.md);
 | ||
| * могут вызывать методы [моделей](structure-models.md) и других компонентов системы с данными запроса;
 | ||
| * могут использовать [представления](structure-views.md) для формирования ответа;
 | ||
| * не должны заниматься обработкой данных, это должно происходить в [слое моделей](structure-models.md);
 | ||
| * должны избегать использования HTML или другой разметки, лучше это делать в [представлениях](structure-views.md).
 | 
