Пользовательским контроллерам необязательно расширять базовый класс.
Но в этом случае у вас не будет доступа ко всем возможностям, таким как
посредники, валидация и другим методам.
Контроллеры
Содержание:
- Введение
- Базовый контроллер
- Контроллер среднего слоя
- Контроллеры ресурсов
- Внедрение зависимости и контроллеры
- Кэширование маршрута
Введение
Вместо определения логигики обработки запроса как замыканий в файлах маршрута, вы можете организовать такое поведение используя классы контроллера. Контроллеры могут сгруппировать похожие по обработке запросов догику в один класс. Они находятся в папке app/Http/Controllers.
Базовый контроллер
Определение котроллера
Ниже представлен пример базового класса контроллера. Данный контроллер расширяет базовый класс контроллера включённый в Ларавел. Базовый класс обеспечивает несколько надёжных методов, таких как метод посредников. Посредника можно прикрепить к дейсвию контроллера:
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 View
*/
public function show($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
Вы можете определить маршрут для данного действия контроллера так:
Route::get('user/{id}', 'UserController@show');
Теперь, когда запрос сопоставят с URI маршрута, запустится выполнения метода show в контроллере UserController. Параметры маршрута будут переданы в метод.
Контроллеры и пространства имён
Важно заметить, что мы не указали пространство имён для контроллера, при определении в маршруте. RouteServiceProvider загружает файлы маршрута, внутри которых содержатся группы с пространстом имён. Нам необходимо лишь указать часть имени класса, которая идёт после App\Http\Controllers.
Если вы хотите разместить ваши контроллеры глубже директории App\Http\Controllers, используйте имена классаов, связанных с пространством имён App\Http\Controllers. Поэтому, если ваш контроллер находится в папке App\Http\Controllers\Photos\AdminController, вам необходимо регистрировать маршрут к контроллеру так:
Route::get('foo', 'Photos\AdminController@method');
Контроллер одного действия
Если вы хотите сделать контроллер с одним одинственным действием, вам необходимо разместить метод __invoke в вашм контроллере:
namespace App\Http\Controllers;
use App\User;
use App\Http\Controllers\Controller;
class ShowProfile extends Controller
{
/**
* Show the profile for the given user.
*
* @param int $id
* @return View
*/
public function __invoke($id)
{
return view('user.profile', ['user' => User::findOrFail($id)]);
}
}
При регистрации маршрутов для контроллера с одиночным действием, метод указывать не нужно:
Route::get('user/{id}', 'ShowProfile');
Одиночные контроллеры можно сгенерировать командой Artisan:
php artisan make:controller ShowProfile --invokable
Контроллер и посредники
Вы можете прикрепить к контроллеру посредника в файле маршрута:
Route::get('profile', 'UserController@show')->middleware('auth');
Часто более удобно указать посредника внутри вашего конструктора контроллера. Используя метод middleware из конструктора контроллера, вы можете легко прикрепить посредника к действию. Также можно детализировать для каких конкретно методов в классе контроллера:
class UserController extends Controller
{
/**
* Instantiate a new controller instance.
*
* @return void
*/
public function __construct()
{
$this->middleware('auth');
$this->middleware('log')->only('index');
$this->middleware('subscribed')->except('store');
}
}
Контроллеры также позволяеют вам регистрировать посредников используя замыкание. Это даёт прекрасный способ определить посредника для одного контроллера без определиния всего класса посредника:
$this->middleware(function ($request, $next) {
// ...
return $next($request);
});
Контроллеры ресурсов
Маршрутизация ресурсов Laravel для типового "CRUD" привязывается к контроллеру с помощью одной строки кода. Например, вы хотите создать контроллер, который обрабатывает все запросы HTTP для фото в вашем приложении. Используя команду Artisan make:controller, вы можете быстро создать такой контроллер:
php artisan make:controller PhotoController --resource
Эта команда сгенерирует контроллер в app/Http/Controllers/PhotoController.php. Контроллер будет содержать соответсвующий метод для каждой из доступных операций ресурса.
Следующим шагом необходимо зарегистрировать маршрут контроллера для ресурса:
Route::resource('photos', 'PhotoController');
Такая декларация создаёт маршруты для обработки множества действий для ресурса. Сгенерированный контроллер будет иметь подготовленные методы для каждого из действий, а также некоторые пометки в виде комментариев для информирования.
Можно регистрировать сразу несколько контроллеров типа "ресурс" путём передачи массива в метод resources:
Route::resources([
'photos' => 'PhotoController',
'posts' => 'PostController'
]);
Действия обрабатываемые контроллером ресурса
Метод | URI | Действие | Имя маршрута |
---|---|---|---|
GET | photos | index | photos.index |
GET | photoscreate | create | photos.create |
POST | photos | store | photos.store |
GET | photos/{photo} | show | photos.show |
GET | photos/{photo}/edit | edit | photos.edit |
PUT/PATCH | photos/{photo} | update | photos.update |
DELETE | photos/{photo} | destroy | photos.destroy |
Детализация модели ресурса
Если вы используете сввзывание модели в маршруте и хотели бы вписывать модели в методы контроллера ресурсов, можно использовать опцию --model при генерации контроллера:
php artisan make:controller PhotoController --resource --model=Photo
Имитация методов форм
В силу того, что HTML формы не могут сделать запросы PUT, PATCH, или DELETE вам необходимо добавить скрытое поле _method, чтобы имитировать эти HTTP методы. Для этого используйте команду Blade @method, которая и создаст это поле:
<form method='POST' action='/foo/bar'>
@method('PUT')
...
</form>
Частичные маршруты ресурса
При декларации маршрута для ресурса, вы можете указать точный набор действий, которые должен выполнять контроллер вместо стандартного набора:
Route::resource('photos', 'PhotoController')->only([
'index', 'show'
]);
Route::resource('photos', 'PhotoController')->except([
'create', 'store', 'update', 'destroy'
]);
API мрашрутов ресурса
При декларации маршрутов API ресурсов вы захотите исключить некоторые пути в которых присутсвует HTML. Например, create и edit. Для удобства, вам необходимо использовать метод apiResource, чтобы исключить данные маршруты:
Route::apiResource('photos', 'PhotoController');
Вы можете регистрировать сразу несколько контроллеров для API ресурсов сразу, путём передачи массива в метод apiResources:
Route::apiResources([
'photos' => 'PhotoController',
'posts' => 'PostController'
]);
Чтобы быстро сгенерировать контроллер API ресурса, которые не включает методы the create или edit, используйте метку --api при выполнении команды make:controller:
php artisan make:controller API/PhotoController --api
Названные имена ресурса
По умолчанию, все действия контроллера ресурсов имеют имена маршрута. Однако, вы может переписать эти имена путём передачи массива names с вашими параметрами:
Route::resource('photos', 'PhotoController')->names([
'create' => 'photos.build'
]);
Параметры названных ресурсов маршрута
По умолчанию, Route::resource создаст параметры маршрута для ваших ресурсов основанных на имени ресурса. Вы можете перезаписать эти имена, используя метод parameters. Массив, который передаётся методу parameters, должен быть ассоциативный массивом имён ресурсов и имён параметров:
Route::resource('users', 'AdminUserController')->parameters([
'users' => 'admin_user'
]);
В приведенном выше примере создаются следующие URI для маршрута ресурса show:
/users/{admin_user}
Локализация URIs ресурсов
По умолчанию, Route::resource содаст URI ресурса на английском языке. Если вам необходима локализация create и edit, вы можете использовать метод Route::resourceVerbs. Это можно сделать в методе boot в вашем AppServiceProvider:
use Illuminate\Support\Facades\Route;
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
Route::resourceVerbs([
'create' => 'crear',
'edit' => 'editar',
]);
}
После такой настройки, регистрация маршрута ресурса такого как Route::resource('fotos', 'PhotoController') создаст следующие URI:
/fotos/crear
/fotos/{foto}/editar
Дополнение ресурса контроллеров
Если вам необходимо добавить дополнительные маршруты для контроллера ресурса за пределами стнадартного набора маршрутов ресурса, вам необходимо определить маршруты до момента вызова Route::resource; в противном случае маршруты определённые методом resource могут невольно иметь приоритет над вашими дополнительными маршрутами:
Route::get('photos/popular', 'PhotoController@method');
Route::resource('photos', 'PhotoController');
Внедрение зависимости и контроллеры
Внедрение в конструктор
Сервис контейнер Laravel используется для работы всех контроллеров. Как результат, вы можете вписывать любые зависимости, которые вам необходимы, в ваш котроллер в его конструктор. Заявленные зависимости будут автоматически внедрены в экземпляр контроллера:
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. Если контейнер может с ним работать, значит вы можете вписать его. В зависимости от приложения, внедрение зависимостей в контроллер может обеспечить лучшую тестируемость.
Внедрение в метод
В дополнение к внедрению в конструктор, вы можете также вписывать зависимости в методы контроллера. Распросранённый пример использования — это внедрение объекта Illuminate\Http\Request в метод контроллера store
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->name;
//
}
}
Если метод контроллера дополнительно ожидает данные и параметров маршрута, перечислите их после зависимостей. Например, если маршрут определён так:
Route::put('user/{id}', 'UserController@update');
Вы можете вписать Illuminate\Http\Request и указать параметр id определяя метод контроллера следующим образом:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
/**
* Update the given user.
*
* @param Request $request
* @param string $id
* @return Response
*/
public function update(Request $request, $id)
{
//
}
}
Кэширование маршрута
Если ваше приложение использует маршруты основанные на контроллерах, вам необходимо воспользоваться преимуществом кэширования маршрутов Laravel. Кэширование позволит вам свести время, необходимое для регистрации всех маршрутов вашего приложения, к минимому. Чтобы сгенерировать кэш маршрутов, выполните команду Artisan route:cache:
php artisan route:cache
После выполнения этой команды, ваш файл закешированных маршрутов будет загружаться для каждого запроса. Важно помнить, что если вы добавляете новые маршруты в приложение, тогда вам будет необходимо сгенерировать новый кэш. Поэтому, выполняйте команду route:cache после завершения основных работ. Например, при развёртывании проекта.
Вы можете использовать команду route:clear, чтобы очистить кэш маршрута:
php artisan route:clear