Простейшие контроллеры
Вместо того, чтобы определять всю маршрутизацию (routing) вашего проекта в файле routes.php вы можете организовать её, используя класс PHPController
. Контроллеры могут группировать связанную логику в отдельные классы, а кроме того использовать дополнительные возможности Laravel, такие как автоматическое внедрение зависимостей.
Контроллеры обычно хранятся в папке app/controllers, а этот путь по умолчанию зарегистрирован в настройке classmap вашего файла composer.json. Тем не менее контроллеры технически могут жить в любом каталоге или подкаталоге. Объявления маршрутов не зависят от расположения на диске файла класса контроллера. Поэтому, пока Composer знает, как автоматически загружать класс контроллера, этот файл может быть размещён где угодно.
Вот пример простейшего класса контроллера:
class UserController extends BaseController {
/**
* Отобразить профиль соответствующего пользователя.
*/
public function showProfile($id)
{
$user = User::find($id);
return View::make('user.profile', array('user' => $user));
}
}
Все контроллеры должны наследовать класс PHPBaseController
. Этот класс также может хранится в папке app/controllers и в него можно поместить общую логику для других контроллеров. PHPBaseController
расширяет стандартный класс Laravel, PHPController
.
Теперь, определив контроллер, мы можем зарегистрировать маршрут для его действия (action):
Route::get('user/{id}', 'UserController@showProfile');
Если вы решили организовать ваши контроллеры в пространства имён, просто используйте полное имя класса при определении маршрута:
Route::get('foo', 'Namespace\FooController@method');
Поскольку мы используем Composer для автозагрузки наших PHP-классов, то контроллеры могут жить где угодно в файловой системе, пока Composer знает, как их загружать. Для каталога контроллера не требуется какая-либо особая структура папок в вашем приложении. Маршрутизация контроллеров полностью отделена от файловой системы.
Помните, что имена класса в строках следуют обычным правилам PHP и если ваш класс начинается с n, t и других букв в нижнем регистре, то обратный слэш перед ними нужно экранировать — иначе они преобразуются в разрыв строки, табуляцию или иной спецсимвол: PHP"namespace\new_controller"
— прим. пер.
Вы также можете присвоить имя этому маршруту:
Route::get('foo', array('uses' => 'FooController@method',
'as' => 'name'));
Вы можете получить URL к действию методом PHPURL::action()
или вспомогательный метод PHPaction()
:
$url = URL::action('FooController@method');
$url = action('FooController@method');
Получить имя действия, которое выполняется в данном запросе, можно методом PHPcurrentRouteAction()
:
$action = Route::currentRouteAction();
Фильтры для контроллеров
Фильтры могут указываться для контроллеров аналогично «обычным» маршрутам:
Route::get('profile', array('before' => 'auth',
'uses' => 'UserController@showProfile'));
Однако вы можете указывать их и изнутри самого контроллера:
class UserController extends BaseController {
/**
* Создать экземпляр класса UserController.
*/
public function __construct()
{
$this->beforeFilter('auth', array('except' => 'getLogin'));
$this->beforeFilter('csrf', array('on' => 'post'));
$this->afterFilter('log', array('only' =>
array('fooAction', 'barAction')));
}
}
Можно устанавливать фильтры в виде функции-замыкания:
class UserController extends BaseController {
/**
* Создать экземпляр класса UserController.
*/
public function __construct()
{
$this->beforeFilter(function () {
//
});
}
}
добавлено в 4.1 ()
Если вы хотите использовать другой метод в качестве фильтра для контроллера, то можете использовать @-синтаксис для определения фильтра:
class UserController extends BaseController {
/**
* Создание нового экземпляра UserController.
*/
public function __construct()
{
$this->beforeFilter('@filterRequests');
}
/**
* Фильтрация входящих запросов.
*/
public function filterRequests($route, $request)
{
//
}
}
Неявные контроллеры
Laravel позволяет вам легко создавать единый маршрут для обработки всех действий контроллера. Для начала зарегистрируйте маршрут методом PHPRoute::controller()
.
Route::controller('users', 'UserController');
До версии 4.2 «неявные» контроллеры назывались «RESTful» — прим. пер.
Метод PHPcontroller()
принимает два аргумента. Первый — корневой URI (путь), который обрабатывает данный контроллер, а второй — имя класса самого контроллера. После регистрации просто добавьте методы в этот класс с префиксом в виде типа HTTP-запроса (HTTP verb), который они обрабатывают.
class UserController extends BaseController {
public function getIndex()
{
// GET-запрос.
}
public function postProfile()
{
// POST-запрос.
}
public function anyLogin()
{
//
}
}
Методы index обрабатывают корневой URI контроллера — в нашем случае это users.
Если имя действия вашего контроллера состоит из нескольких слов вы можете обратиться к нему по URI, используя синтаксис с дефисами (-). Например, следующее действие в нашем классе PHPUserController
будет доступно по адресу users/admin-profile:
public function getAdminProfile() {}
RESTful-контроллеры ресурсов
Контроллеры ресурсов упрощают построение RESTful-контроллеров, работающих с ресурсами. Например, вы можете создать контроллер, обрабатывающий фотографии, хранимые вашим приложением. Вы можете быстро создать такой контроллер с помощью команды controller:make интерфейса Artisan и метода PHPRoute::resource()
.
До версии 4.2 эти контроллеры назывались просто ресурсными, а RESTful были те, что с этой версии стали называться «неявными» — прим. пер.
Для создания контроллера выполните следующую консольную команду:
shphp artisan controller:make PhotoController
Теперь мы можем зарегистрировать его как контроллер ресурса:
Route::resource('photo', 'PhotoController');
Этот единственный вызов создаёт множество маршрутов для обработки различных RESTful-действий на ресурсе photo. Сам сгенерированный контроллер уже имеет методы-заглушки для каждого из этих маршрутов с комментариями, которые напоминают вам о том, какие типы запросов они обрабатывают.
Запросы, обрабатываемые контроллером ресурсов
Тип | Путь | Действие | Имя маршрута |
---|---|---|---|
GET | /resource | index | resource.index |
GET | /resource/create | create | resource.create |
POST | /resource | store | resource.store |
GET | /resource/{resource} | show | resource.show |
GET | /resource/{resource}/edit | edit | resource.edit |
PUT/PATCH | /resource/{resource} | update | resource.update |
DELETE | /resource/{resource} | destroy | resource.destroy |
Иногда вам может быть нужно обрабатывать только часть всех возможных действий:
shphp artisan controller:make PhotoController --only=index,show php artisan controller:make PhotoController --except=index
Вы можете указать этот набор и при регистрации маршрута:
Route::resource('photo', 'PhotoController',
array('only' => array('index', 'show')));
// либо:
Route::resource('photo', 'PhotoController',
array('except' => array('create', 'store', 'update', 'destroy')));
добавлено в 4.1 ()
добавлено в 4.2 ()
Обработка контроллеров вложенных ресурсов
Используйте «точечную» нотацию в объявлении маршрута для контроллеров «вложенных» ресурсов:
Route::resource('photos.comments', 'PhotoCommentController');
Этот маршрут зарегистрирует «вложенный» ресурс, к которому можно обратиться по такому URL: photos/{photoResource}/comments/{commentResource}.
class PhotoCommentController extends BaseController {
public function show($photoId, $commentId)
{
//
}
}
Добавление дополнительных маршрутов в контроллеры ресурсов
Когда вам необходимо добавить дополнительные маршруты в контроллер ресурсов, не входящие в маршруты ресурсов по умолчанию, их надо определить до вызова PHPRoute::resource
:
Route::get('photos/popular');
Route::resource('photos', 'PhotoController');
Обработка неопределённых методов
При использовании PHPRoute::controller
можно определить «catch-all» метод, который будет вызываться для обработки запроса, когда в контроллере нет соответствующего метода. Он должен называться missingMethod и принимать массив методов и параметров запроса в виде единственного своего аргумента.
public function missingMethod($parameters = array())
{
//
}
При использовании контроллеров ресурсов необходимо определить для них волшебный метод PHP__call
, чтобы обрабатывать любые отсутствующие методы.