Контроллер в парадигме MVC связывает модель и представление. Когда нужно визуализировать данные, контроллер получает их из модели и предает в представление. Если же нужно изменить данные, контроллер передает их в модель, но сам операций по управлению данными не производит.
Создание контроллера
Файлы контроллеров располагаются в папке classes/controller
согласно файловой системе. Каждый контроллер должен удовлетворять следующим пунктам:
-
Имя файла контроллера должно быть написано в нижнем регистре:
classes/controller/welcome.php
-
Каждое слово в названии контроллера, наоборот, должно быть с большой буквы:
Controller_Welcome
. -
При использовании поддиректорий (Директива
directory
в роутах), это должно отображаться на имени класса контроллера. Например, если файл называетсяclasses/controller/account/register.php
, то класс контроллера должен называтьсяController_Account_Register
.
Класс контроллера должен наследовать класс Controller
(не обязательно напрямую):
class Controller_Welcome extends Controller { public function action_index() {} }
Использование контроллеров
Контроллеры запускаются через обращения, в зависимости от настроенных роутов (рекомендуется сначала прочитать эти разделы). После того, как роут определяет, какой контроллер вызвать, происходят следующие действия:
-
Вызывается метод контроллера
before()
. В этот метод помещают действия, которые должны быть выполнены до любогоaction
, это: определение языка посетителя, генерация одинакового для каждой страницы меню и прочие подобные действия. -
В зависимости от определенного параметра роута
action
, вызывается метод контроллераaction_action
. Например, приaction
=index
, вызывается методaction_index
. В этом методе пишется функциональный код контроллера. -
Вызывается метод контроллера
after()
. В этом методе обычно помещают завершающие действия, это — закрытие дескрипторов, генерация некоторых представлений и т.д.
Response (Ответ)
Для работы с ответом Kohana предоставляет класс Response
, который доступен из контроллера как $this->response
. Результатом работы любого контроллера является сгенерированный ответ — представление либо комбинация представлений, в основном это HTML-код. Установить ответ можно с помощью метода $this->response->body($content)
:
$this->response->body('Задание выполнено!');
Подробнее об ответе вы можете прочитать в разделе Response (Ответ).
Request (Обращение)
Для работы с обращением изпользуется класс Request
, из контроллера текущее обращение доступно как $this->request
.
Для получения имени текущего контроллера, используйте метод controller()
:
$controller_name = $this->request->controller();
Для получения текущего действия (Action) ипользуется метод action()
:
$action_name = $this->request->action();
Для получения параметров роута используется метод param($key, $default)
, где $key
— название параметра, $default
— значение, которое будет возвращено, если параметр не существует:
$id = $this->request->param('id', 0);
Если параметр $key
не передавать, то будет возвращен весь список параметров:
$params = $this->request->param();
Подробнее об обращении читайте в разделе Request (Обращение)
Actions (Действия)
Действие в контроллере — это метод, который выполняет определенную задачу. Например, простейший метод, который выводит в браузер строку Hello Browser!
:
public function action_index() { $this->response->body('Hello Browser!'); }
И действие посложнее, которое использует модель и представление:
public function action_index() { // Получаем данные из модели $categories = Model::factory('Categories')->list_all(); // Генерируем представление, используя эти данные $this->response->body(View::factory('content/categories') ->bind('categories', $categories)); }
Before и After
Методы before()
и after()
запускаются до и соответственно после каждого действия в текущем контроллере. Это позволяет реализовать функции, которые должны выполняться для любого действия контроллера. Например, для контроллера панели администрирования в методе before()
реализуется проверка, является ли текущий пользователь администратором? имеет ли он доступ к текущему действию? и т.д.
class Controller_Admin extends Controller { public function before() { $action = $this->request->action(); // Проверяем, имеет ли пользователь админ-доступ, в том числе и к текущему действию if ( !Auth::instance()->logged_in('admin') || !Auth::instance()->logged_in('admin_'.$action)) { // Если доступ запрещен, то генерируем ошибку 403 Forbidden throw new HTTP_Exception_403(); } } // Дальнейшие действия
Если вы используете несколько уровней наследования, то для вызова этого же метода у родительского класса нужно использовать функцию parent::method
, где method
— название метода, например:
class Controller_Admin extends Controller_Project { public function before() { // Выполняем функцию родительского класса parent::before(); // Выполняем свой метод дальше do_some(); }
Расширенные контроллеры
Расширенные контроллеры предоставляют дополнительный функционал для наследуемого класса.
Шаблон
В комплекте с Kohana идет расширенный контроллер Controller_Template
, который реализует простейшую шаблонизацию. Он позволяет вам выбирать представление, которое будет создаваться при старте контроллера и доступное через $this->template
. После завершения выполнения контроллера, это представление автоматически сгенерируется в ответ (response
) контроллера. Для его использования, вы должны объявить свой контроллер, унаследовав Controller_Template
:
class Controller_Index extends Controller_Template { public $template = 'default'; public $auto_render = TRUE; }
Для настройки контроллера доступно две переменных:
-
$template
— имя представления, которое будет использовано как шаблон. -
$auto_render
— генерировать ли шаблон в ответ (response
) по выполнению контроллера?
Пример использования
Контроллер classes/controller/index.php
:
class Controller_Index extends Controller_Template { public $template = 'default'; public function before() { parent::before(); // Для любого action передаем шаблону какие-нибудь данные $this->template->categories = array('PHP', 'Kohana', 'Framework'); } public function action_index() { // Генерируем представление и передаем шаблону $this->template->content = View::factory('content/index'); } public function action_contacts() { // Для другого action генерируем другое представление $this->template->content = View::factory('content/contacts'); } }
Представление views/default.php
Добро пожаловать! Список категорий: <?=View::factory('content/categories')->bind('categories', $categories)?> <?=$content?>
Представление views/content/index.php
Основное содержимое.
Представление views/content/categories.php
<?=implode($categories, ', ')?>
На основе этого получится примерный результат:
Добро пожаловать! Список категорий: PHP, Kohana, Framework Основное содержимое