Основы
Контроллеры — это классы, принимающие пользовательский ввод и взаимодействующие с моделями, библиотеками и видами (представлениями, «views»). В общем случае они запрашивают у модели данные и передают его виду, который формирует страницу, передаваемую клиенту.
Использование контроллеров — обычная практика в современных вёб-приложениях, однако Laravel также позволяет разработчику реализовать собственную логику используя маршруты («routes»). Новичкам следует начать с использования контроллеров, хотя в них нет ничего, что нельзя было бы реализовать с помощью маршрутов.
Классы контроллеров хранятся в application/controllers и наследуются от класса PHPBase_Controller. Изначально Laravel также содержит класс-заготовку PHPHome_Controller для отображения домашней страницы (вида home.index).
Простейший контроллер
class Admin_Controller extends Base_Controller {
public function action_index() {
// код отображения страницы index.
}
}
Действия («actions») — это методы контроллера, которые должны быть доступны при запросе из сети. Методы действий начинаются с action_; все прочие методы класса-контроллера будут не доступны из сети.
PHPBase_Controller расширяет фундаментальный класс PHPController — вы можете поместить в него свои методы, используемые многими вашими контроллерами и наследовать их классы от него.
Маршрутизация
Важно понимать, что в Laravel все маршруты («routes») должны быть явно зарегистрированы — даже те, что обрабатываются контроллерами.
Это значит, что методы контроллера, которые не были зарегистрированы не доступны запросам из сети. Однако есть возможность автоматически зарегистрировать все действия контроллера — обычно это делается в application/routes.php (см. «Маршрутизация»).
Контроллеры в пакетах
Laravel предоставляет систему пакетов, или сборок («bundles») — независимых модулей, которые вы можете использовать в своём приложении. Пакеты могут быть назначены на обработчики определённых запросов — см. «Пакеты».
Создание контроллеров, принадлежащих пакету, почти не отличается от создания обычных контроллеров для вашего вёб-приложения (в application/controllers) — для начала начните имя класса-контроллеров с имени пакета. Например, для пакета «admin» класс-контроллер «home» может выглядеть так:
class Admin_Home_Controller extends Base_Controller {
public function action_index() {
return "Hello Admin!";
}
}
Как зарегистрировать пакетный контроллер? Просто:
Route::controller('admin::home');
Отлично! Теперь мы можем запросить наш контроллер «home» пакета «admin», открыв эту страницу в браузере:
http://localhost/home/
А если для этого контроллера была задана опция handles в application/routes.php (например, admin) — то адрес доступа будет выглядеть так:
http://localhost/admin/home/
Двойное двоеточие (::) используется в различных функциях Laravel для задания имени пакета.
Фильтры для действий
Фильтры — это метод, вызываемые до или после вызова определённого действия контроллера («controller action»). В Laravel, вы можете не только привязывать фильтры к действиям, но и определять, для какого из метода запроса HTTP (GET, POST, PUT или DELETE) этот фильтр будет вызван.
Вы можете привязать фильтр «до» (before) или «после» (after) из конструктора класса-контроллера — например, так можно привязать фильтр ко всем его действиям:
$this->filter('before', 'auth');
В этом примере фильтр auth будет вызван перед (before) вызовом любого действия, принадлежащего этому контроллеру. Действие auth — стандартное для Laravel и умолчательный обработчик для него уже задан в application/routes.php — если клиент не вошёл в систему, он переадресует его на форму авторизации.
Привязка к действиям
$this->filter('before', 'auth')->only(array('index', 'list'));
В этом примере фильтр auth будет вызван перед вызовом метода-действия PHPaction_index или PHPaction_list текущего контроллера (PHP$this). Клиент должен быть авторизован для того, чтобы они были вызваны (таким образом, их страницы не будут доступны). Однако для всех других действий этого не требуется.
Привязка ко всем, кроме...
$this->filter('before', 'auth')->except(array('add', 'posts'));
Этот пример напоминает пример выше — он привязывает фильтр к методам текущего контроллера, но не ко всем перечисленным, а ко всем, кроме перечисленных.. Это значит, что здесь мы определяем действия, для которых не будет запрошена авторизация — используется метод PHPFilter_Collection->except.
Иногда этот подход более безопасен, так как можно добавлять к контроллеру новые действия без опасения забыть перечислить их в списке, требующих авторизации.
Привязка к POST-запросу
$this->filter('before', 'csrf')->on('post');
Этот пример показывает, как фильтр может быть привязан к определённому виду HTTP-запроса (так называемый «verb»). В этом случае фильтр csrf Будет вызван только для POST-запроса, то есть когда была отправлена форма. Фильтр csrf позволяет заблокировать отправку формы, которая не была заполнена непосредственно самим клиентом — это один из приёмов фишинга, см. статью CSRF.
Фильтр csrf включен в состав Laravel и по умолчанию определён в application/routes.php.
Вложенные контроллеры
Контроллеры могут быть расположены в любой папке любой вложенности внутри application/controllers.
Например, для определения подконтроллера «panel» контроллера «admin» поместите код его класса в controllers/admin/panel.php:
class Admin_Panel_Controller extends Base_Controller {
public function action_index() {
// код действия index.
}
}
Теперь зарегистрируйте вложенный контроллер в списке маршрутов используя синтаксис с точками:
Route::controller('admin.panel');
Внимание: регистрируя вложенные контроллеры всегда начинайте с самых вложенных, чтобы маршруты внешних контроллеров не перекрывали вложенные.
Теперь этот контроллер доступен по этому адресу:
http://localhost/admin/panel
REST-контроллеры
REST (передача состояния представления, Representational State Transfer) — способ передачи информации о предыдущих действиях клиента в рамках его сессии. Сюда относятся, например, поля заполненной на предыдущей странице формы.
Если имя метода действие контроллера начинается не с action_, а с одного из форм HTTP-запросов, то он будет отвечать только на него. Это требует добавить свойство «restful» в класс-контроллер:
class Home_Controller extends Base_Controller {
public $restful = true;
}
class Home_Controller extends Base_Controller {
public $restful = true;
public function get_index() {
// обработка GET-запроса страницы index.
}
public function post_index() {
// обработка POST-запроса страницы index.
}
}
Это особенно удобно при создании CRUD-методов — вы можете отделить код, заполняющий и выводящий форму от кода проверки и сохранения её данных.
Внедрение зависимостей
Если вы стремитесь писать тестируемый код вы, возможно, хотите указать зависимости в конструкторе вашего контроллера. Это не проблема — просто зарегистрируйте его в IoC-контейнере, не забыв поставить перед ним префикс controller:. Мы можем зарегистрировать наш контроллер user в application/start.php:
IoC::register('controller: user', function () {
return new User_Controller;
});
Когда будет получен запрос вызова этого контроллера Laravel автоматически определит, зарегистрирован ли он в контейнере и если да, то он использует его для создания экземпляра класса контроллера.
Перед внедрением зависимостей ознакомьтесь со статьёй об IoC-контейнере.
Фабрика контроллеров
Если вам нужно ещё больше контроля за созданием экземпляров класса-контроллера, например, при использовании стороннего IoC-контейнера, то обратитесь к фабрике контроллеров.
Регистрация события, создающего экземпляр контроллера:
Event::listen(Controller::factory, function ($controller) {
return new $controller;
});
Событие PHPController::factory принимает имя контроллера, который должен быть создан. Всё, что вам нужно — вернуть экземпляр его класса.
Laravel по-русски