git 4ada7c705933b9bf39f51bd8e1f9c71d9fa323b0
- Введение
- Простейшие контроллеры
- Использование посредников с контроллерами
- RESTful ресурс-контроллеры
- Внедрение зависимостей в контроллерах
- Кэширование маршрутов
Вместо того, чтобы писать логику обработки запросов в файле routes.php, вы можете организовать её, используя классы Controller, которые позволяют группировать связанные обработчики запросов в отдельные классы. Контроллеры хранятся в папке app/Http/Controllers.
Все Laravel контроллеры должны расширять базовый класс контроллера, присутствующий в Laravel по умолчанию. Пример простейшего класса контроллера:
<?php
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class UserController extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return Response
*/
public function showProfile($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
Привязка метода контроллера к маршруту выглядит так:
Route::get('user/{id}', 'UserController@showProfile');
Теперь при совпадении запроса со строкой 'user/{id}' будет вызван метод showProfile класса UserController. В метод будет передан параметр {id}.
Очень важно отметить, что нам не пришлось указывать всё пространство имён контроллера при опеределении марщрута. Мы определили только ту пространства имен класса, которая идёт после корня App\Http\Controllers. Так происходит, поскольку, по умолчанию, класс RouteServiceProvider загружает все маршруты из файла routes.php в группу с этим «корневым» пространством имён.
Если вы решите наследовать или организовать ваши контроллеры используя пространства имён глубже в папке App\Http\Controllers, просто используйте название класса относительно корневого пространства имён App\Http\Controllers. Таким образом, если ваш полный класс App\Http\Controllers\Photos\AdminController, регистрация маршрута будет выглядеть так:
Route::get('foo', 'Photos\AdminController@method');
Как и в случае с обработчиками-замыканиями, вы можете присвоить имя этому роуту:
Route::get('foo', ['uses' => 'FooController@method', 'as' => 'name']);
Вы можете использовать функцию-помощник route для создания URl к маршруту
$url = route('name');
Посредники могут быть привязаны к маршрутам следующим образом:
Route::get('profile', [
'middleware' => 'auth',
'uses' => 'UserController@showProfile'
]);
Но более удобно назначать посредника в конструкторе контроллера. Используя метод middleware в конструкторе, вы можете легко назначать посредника для контроллера. Вы даже можете использовать посредника только для определенных методов контроллера:
class UserController extends Controller
{
/**
* Instantiate a new UserController instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log', ['only' => [
'fooAction',
'barAction',
]]);
$this->middleware('subscribed', ['except' => [
'fooAction',
'barAction',
]]);
}
}
Ресурс-контроллеры упрощают построение RESTful контроллеров, работающих с ресурсами. Например, вы можете создать контроллер, обрабатывающий фотографии, хранимые вашим приложением. Вы можете быстро создать такой контроллер, используя Artisan-команду make:controller.
Для создания контроллера выполните следующую консольную команду:
php artisan make:controller PhotoController --resource
Команда создаст файл контроллера app/Http/Controllers/PhotoController.php. Контроллер будет содержать методы для всех доступных действий с ресурсами.
Далее вы можете создать маршрут-ресурс для этого контроллера:
Route::resource('photo', 'PhotoController');
Это единственное определение маршрута на самом деле описывает несколько маршрутов для обработки различных RESTful действий для ресурса photo. Сгенерированный контроллер уже имеет методы-заглушки для каждого из этих маршрутов с комментариями, которые напоминают о том, какие URI и типы запросов они обрабатывают.
| Глагол | путь | Действие | Имя маршрута |
|---|---|---|---|
| GET | /photo |
index | photo.index |
| GET | /photo/create |
create | photo.create |
| POST | /photo |
store | photo.store |
| GET | /photo/{photo} |
show | photo.show |
| GET | /photo/{photo}/edit |
edit | photo.edit |
| PUT/PATCH | /photo/{photo} |
update | photo.update |
| DELETE | /photo/{photo} |
destroy | photo.destroy |
При задании ресурс-роута вы можете определить только часть из всех возможных действий:
Route::resource('photo', 'PhotoController', ['only' => [
'index', 'show'
]]);
Route::resource('photo', 'PhotoController', ['except' => [
'create', 'store', 'update', 'destroy'
]]);
По умолчанию, все действия ресурс контроллеров имеют имя в формате «ресурс.действие». Однако, вы можете изменить эти имена, используя массив names в опциях:
Route::resource('photo', 'PhotoController', ['names' => [
'create' => 'photo.build'
]]);
По умолчанию статический метод Route::resource будет создавать параметры маршрута для вашего ресурса, используя имя ресурса. Вы можете изменить это, оперделив в массиве опций ключ parameters. Ключ должен быть массивом, в котором задана пара 'имя ресурса'=>'имя параметра':
Route::resource('user', 'AdminUserController', ['parameters' => [
'user' => 'admin_user'
]]);
Пример выше задает следующий URIs для действия show:
/user/{admin_user}
Вместо задания массива для ключа 'parameters' вы можете присвоить ему значение singular, что укажет Laravel использовать имена параметров по умолчанию, но в единственном числе ("singularize"):
Route::resource('users.photos', 'PhotoController', [
'parameters' => 'singular'
]);
// /users/{user}/photos/{photo}
Альтернативно, вы можете установить глобально: значение singular, имена для параметров ресурсов
Route::singularResourceParameters();
Route::resourceParameters([
'user' => 'person', 'photo' => 'image'
]);
При настройке параметров ресурса важно помнить приоритет назначения имен:
- Параметры явно определенные в
Route::resource. - Глобальный параметр установленный посредством
Route::resourceParameters. - Параметр
singular, заданный через ключparametersвRoute::resourceили посредствомRoute::singularResourceParameters. - Поведение по умолчанию.
Если необходимо определить дополнительные маршруты для ресурс-контроллера помимио маршрутов по умолчанию, вы должны определять их
перед вызовом Route::resource; иначе, маршруты, определенные через метод resource могут иметь приоритет над вашими дополнительными маршрутами:
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
Laravel сервис-контейнер используется для поиска и получения всех контроллеров. За счёт этого вы можете указать любые зависимости в качестве аргументов конструктора вашего контроллера. Зависимости будут автоматически разрешены и внедрены в экземпляр контроллера:
<?php
namespace App\Http\Controllers;
use App\Repositories\UserRepository;
class UserController extends Controller
{
/**
* The user repository instance.
*/
protected $users;
/**
* Create a new controller instance.
*
* @param UserRepository $users
* @return void
*/
public function __construct(UserRepository $users)
{
$this->users = $users;
}
}
Конечно, вы можете использовать в качестве зависимости любой контракт Laravel contract. Если контейнер может его разрешить, вы можете его использовать в контроле типов.
Точно так же можно указывать зависимости для любого метода контролера. Например, давайте укажем Illuminate\Http\Request как зависимость для метода store:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Store a new user.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
$name = $request->input('name');
//
}
}
Если метод контроллера так же ожидает какие-либо данные из маршрута, то можно просто указать их после других зависимостей. Например, если маршрут задан так:
Route::put('user/{id}', 'UserController@update');
Вы может использовать зависимость от Illuminate\Http\Request и иметь доступ к параметру id, определив их в методе:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Update the specified user.
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
Примечание: Кэширование не работает с маршрутами на основе замыканий. Для таких маршрутов для использования кэширования требуется заменить замыкания на контроллеры.
Если ваше приложении использует маршруты исключительно на основе контроллеров, вы должны получить примущество кеширования. Использование кэширования значительно уменьшает время для регистрации всех маршрутов приложения. В некоторых случаях получается 100-кратное ускорение регистрации. Для создания кэша маршрутов нужно только выполнить в консоли Artisan команду route:cache:and:
php artisan route:cache
Теперь сгенерированный кэш-файл маршрутов будет использоваться вместо файла app/Http/routes.php. Помните, что при добавлении новых или изменении существующих маршрутов необходимо пересоздавать кэш, поэтому лучше использовать кэширование маршрутов только при развёртывании приложения.
Для удаления кэша маршрутов без генерации нового используется Artisan-команда route:clear:
php artisan route:clear