Все посредники функционируют через сервис контейнер, поэтому вы можете
вписать любую зависимость, которая вам необходима, в конструктор.
Посредники
Содержание:
Введение
Посредники (англ. Middleware) обеспечивают надёжный механизм фильтрации HTTP запросов, которые поступают в приложение. Например, Laravel включает посредника, который проводит процедуру верификации на предмет того, что пользователь прошёл аутентификацию. Если пользователь не аутинтифицирован, посредник перенаправит пользователя на страницу авторизации. А если пользователь прошёл аутентификацию, тогда посредник даст разрешение на выполнение первоначального запроса.
Посредник может выполнять множество других заданий перед аутентификацией. Посредник CORS может отвечать за заголовки, которые исходят из вашего приложения. Дополнительно может вестись учёт всех поступающих запрос в приложение.
Есть несколько посредников, которые уже включены в фреймворк, включая посредника для аутинтификации и CSRF защиты. Все эти посредники расположены в папке app/Http/Middleware.
Определение посредника
Чтобы создать нового посредника, используйте команду Artisan make:middleware:
php artisan make:middleware CheckAge
Эта команда создаст новый класс CheckAge внутри папки app/Http/Middleware. В этом посреднике, вы позволите запросу пройти дальше, если выполняется условие, что возраст больше 200. В противном случае, вас перенаправят на домашнюю страницу:
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ($request->age <= 200) {
return redirect('home');
}
return $next($request);
}
}
Как вы можете видеть, если представленный возраст age меньше или равен 200, посредник вернёт перенаправление HTTP на клиента, в противном случае, запрос пройдёт дальше в приложение. Чтобы пропустить запрос дальше в приложение, вызовите $next с $request.
Лучше всего представлять посредника как слои, которые HTTP запросы должны пройти перед тем, как достичь ядра приложения. Каждый слой тестирует запрос на выполнение условий или даже отклоняет запрос полностью.
До и после посредника
Момент запуска посредника до или после запроса зависит от самого посредника. Например, следующий посредник будет выполнять задание до момента, когда запрос пройдёт ядро приложения:
namespace App\Http\Middleware;
use Closure;
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// Perform action
return $next($request);
}
}
А этот посредник выполнить задание после прохождения запроса в приложении:
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// Perform action
return $response;
}
}
Регистрация посредника
Глобальный посредник
Если вы хотите запускать посредника для каждого HTTP запроса в вашем приложении, укажите класс посредника в свойстве $middleware класса app/Http/Kernel.php.
Назначение посредника маршрутам
Если вы хотите назначить посредника для определённого маршрута, вы должны указать ключ посредника в вашем файле app/Http/Kernel.php. По умолчанию, свойство $routeMiddleware этого класса содержит записи для посредников, включённых в Ларавел. Чтобы добавить ваш собственный, добавьте его в конец списка с придуманным вами ключом:
// Within App\Http\Kernel Class...
protected $routeMiddleware = [
'auth' => \App\Http\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'cache.headers' => \Illuminate\Http\Middleware\SetCacheHeaders::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class,
];
После того, как посредник был определён в вашем ядре HTTP, вы можете использовать метод, чтобы приписать middleware к маршруту:
Route::get('admin/profile', function () {
//
})->middleware('auth');
Вы можете приписывать несколько посредников к маршруту:
Route::get('/', function () {
//
})->middleware('first', 'second');
Когда вы прикрепляете посредника, можно еще и передать полное имя класса:
use App\Http\Middleware\CheckAge;
Route::get('admin/profile', function () {
//
})->middleware(CheckAge::class);
Группы посредников
Иногда может возникнуть ситуация, когда необходимость сгруппировать посредников под одним ключом, чтобы упростить прикрепление к маршруту. Для этого необходимо использовать свойство $middlewareGroups ядра HTTP.
Из коробки, Ларавел имеет в коплекте группы посредников web и api, которые содержат посредники что вы могли бы прикрепить к вашим UI и API маршрутам:
/**
* The application's route middleware groups.
*
* @var array
*/
protected $middlewareGroups = [
'web' => [
\App\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
],
'api' => [
'throttle:60,1',
'auth:api',
],
];
Группы посредников могут быть присоединены к маршрутам и действиям контроллера используя такой же синтаксис как и одиночный посредник. Опять же, группы посредников позволяют посредников к маршрутам более удобным способом:
Route::get('/', function () {
//
})->middleware('web');
Route::group(['middleware' => ['web']], function () {
//
});
Сортирование посредников
Иногда, вам может понадобиться выполнение посредников в определённом порядке. Но возможности определять порядок при назначении посредников маршруту нет. В этом случае, вам необходимо указать порядок выполнения посредников используя свойство $middlewarePriority в файле app/Http/Kernel.php:
/**
* The priority-sorted list of middleware.
*
* This forces non-global middleware to always be in the given order.
*
* @var array
*/
protected $middlewarePriority = [
\Illuminate\Session\Middleware\StartSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\App\Http\Middleware\Authenticate::class,
\Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
\Illuminate\Auth\Middleware\Authorize::class,
];
Параметры посредника
Пссредники также могут принимать дополнительные параметры. Например, если вашему приложения необходимо провести верификацию того, что пользователь имеет определённную роль до выполнения действия, вам необходимо создать посредника CheckRole. Такой посредник будет получать имя роли в качестве дополнительного аргумента.
Дополнительные параметры будут передавить посредники после аргумента $next:
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* Handle the incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @param string $role
* @return mixed
*/
public function handle($request, Closure $next, $role)
{
if (! $request->user()->hasRole($role)) {
// Redirect...
}
return $next($request);
}
}
Параметры посредника можно указать при определении маршрута путём отделения имени и параметра через :. Несолько параметров должны разделяться запятыми:
Route::put('post/{id}', function ($id) {
//
})->middleware('role:editor');
Срочный посредник
Иногда может потребоваться, чтобы посредник выполнил определённую работу после того, как HTTP ответ отправлен браузеру. Например, посредник сессия, включённые в Ларавел, записывает данные сессии, чтобы сохранить после ответа браузеру. Если вы определите метод terminate для посредника и ваш сервер использует FastCGI, тогда метод terminate будет выполняться сразу же после отправки ответа браузеру.
namespace Illuminate\Session\Middleware;
use Closure;
class StartSession
{
public function handle($request, Closure $next)
{
return $next($request);
}
public function terminate($request, $response)
{
// Store the session data...
}
}
Метод terminate должен принимать и запросы и ответы. После определения, вы должны добавить в список глобальных посредников в файле app/Http/Kernel.php.
При обращении к методу terminate, Ларавел получить новый объект посредника из сервис контейнера. Если вы хотите использовать один и тот же объект посредника при вызове методов handle и terminate, зарегистрируйте посредника используя метод singleton.