Может войдёшь?
Черновики Написать статью Профиль

Middleware

перевод документация 5.х

  1. 1. Введение
  2. 2. Создание посредника
    1. 2.1. Посредник «до» и «после»
  3. 3. Регистрация посредника
    1. 3.1. Глобальный посредник
    2. 3.2. Назначение посредника для маршрутов
  4. 4. Параметры посредника
  5. 5. Посредник terminable
Этот перевод актуален для англоязычной документации на (ветка 5.1) и (ветка 5.0). Опечатка? Выдели и нажми Ctrl+Enter.

Введение

HTTP-посредники (англ. middleware) предоставляют удобный механизм для фильтрации HTTP-запросов вашего приложения. Например, в Laravel есть посредник для проверки аутентификации пользователя. Если пользователь не аутентифицирован, посредник перенаправит его на экран входа в систему. Если же пользователь аутентифицирован, посредник позволит запросу пройти далее в приложение.

Конечно, посредники нужны не только для авторизации. CORS-посредник может пригодиться для добавления особых заголовков ко всем ответам в вашем приложении. А посредник логов может зарегистрировать все входящие запросы.

В Laravel есть несколько стандартных посредников, включая посредники для обслуживания, аутентификации, CSRF-защиты и многие другие. Все они расположены в каталоге app/Http/Middleware.

Создание посредника

Чтобы создать посредника, используйте команду Artisan shmake:middleware:

shphp artisan make:middleware OldMiddleware

Эта команда поместит новый класс OldMiddleware в ваш каталог app/Http/Middleware. В этом посреднике мы будем пропускать только те запросы, в которых age будет больше 200, а во всех остальных случаях будем перенаправлять пользователей на «home» URI.

PHP
<?php

namespace App\Http\Middleware;

use 
Closure;

class 
OldMiddleware
{
  
/**
   * Выполнение фильтра запроса.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \Closure  $next
   * @return mixed
   */
  
public function handle($requestClosure $next)
  {
    if (
$request->input('age') <= 200) {
      return 
redirect('home');
    }

    return 
$next($request);
  }

}

Как видите, если переданный age меньше или равен 200, то посредник вернёт клиенту переадресацию, иначе, запрос будет передан далее в приложение. Чтобы передать запрос дальше в приложение (позволяя посреднику «передать» его), просто вызовите замыкание PHP$next с параметром PHP$request.

Проще всего представить посредника как набор «уровней», которые должен пройти HTTP-запрос, прежде чем он дойдёт до вашего приложения. Каждый уровень может проверить запрос и даже вовсе отклонить его.

Посредник «до» и «после»

Момент, в который сработает посредник — до или после запроса, зависит от него самого. Например, этот посредник выполнит некоторую задачу прежде, чем запрос будет обработан приложением:

PHP
<?php

namespace App\Http\Middleware;

use 
Closure;

class 
BeforeMiddleware
{
  public function 
handle($requestClosure $next)
  {
    
// Выполнение действия

    
return $next($request);
  }
}

А этот посредник выполнит задачу после того, как запрос будет обработан приложением:

PHP
<?php

namespace App\Http\Middleware;

use 
Closure;

class 
AfterMiddleware
{
  public function 
handle($requestClosure $next)
  {
    
$response $next($request);

    
// Выполнение действия

    
return $response;
  }
}

Регистрация посредника

Глобальный посредник

Если вы хотите, чтобы посредник запускался для каждого HTTP-запроса в вашем приложении, добавьте этот посредник в свойство PHP$middleware класса app/Http/Kernel.php.

Назначение посредника для маршрутов

Если вы хотите назначить посредника для конкретных маршрутов, то сначала вам надо добавить сокращённый ключ посредника в класс app/Http/Kernel.php. По умолчанию свойство PHP$routeMiddleware этого класса содержит записи посредников Laravel. Чтобы добавить ваш собственный посредник, просто добавьте его к этому списку и присвойте ему ключ на свой выбор. Например:

PHP
// в классе App\Http\Kernel...

protected $routeMiddleware = [
  
'auth' => \App\Http\Middleware\Authenticate::class,
  
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
  
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
];

Когда посредник определён в HTTP-ядре, вы можете использовать ключ middleware в массиве параметров маршрута:

PHP
Route::get('admin/profile', ['middleware' => 'auth', function () {
  
//
}]);

Используйте массив для назначения нескольких посредников для маршрута:

PHP
Route::get('/', ['middleware' => ['first''second'], function () {
  
//
}]);

Вместо использования массива вы можете использовать сцепку метода PHPmiddleware() с определением маршрута:

PHP
Route::get('/', function () {
  
//
})->middleware(['first''second']);

Параметры посредника

В посредник можно передавать свои дополнительные параметры. Например, если в вашем приложении необходима проверка того, есть ли у аутентифицированного пользователя определённая «роль» для выполнения данного действия, вы можете создать посредника RoleMiddleware, который принимает название роли в качестве дополнительного аргумента.

Дополнительные параметры посредника будут передаваться в посредник после аргумента PHP$next:

PHP
<?php

namespace App\Http\Middleware;

use 
Closure;

class 
RoleMiddleware
{
  
/**
   * Выполнение фильтрации запроса.
   *
   * @param  \Illuminate\Http\Request  $request
   * @param  \Closure  $next
   * @param  string  $role
   * @return mixed
   */
  
public function handle($requestClosure $next$role)
  {
    if (! 
$request->user()->hasRole($role)) {
      
// Redirect...
    
}

    return 
$next($request);
  }

}

Параметры посредника можно указать при определении маршрута, разделив название посредника и параметры двоеточием :. Параметры разделяются запятыми:

PHP
Route::put('post/{id}', ['middleware' => 'role:editor', function ($id) {
  
//
}]);

Посредник terminable

Иногда посредник должен выполнить некоторые действия уже после отправки HTTP-ответа браузеру. Например, посредник «session», поставляемый с Laravel, записывает данные сессии в хранилище после отправки ответа в браузер. Для этого нужно определить посредника как «terminable», добавив в него метод PHPterminate():

PHP
<?php

namespace Illuminate\Session\Middleware;

use 
Closure;

class 
StartSession
{
  public function 
handle($requestClosure $next)
  {
    return 
$next($request);
  }

  public function 
terminate($request$response)
  {
    
// Сохранение данных сессии...
  
}

}

Метод PHPterminate() получает и запрос, и ответ. Определив посредника как «terminable», вы должны добавить его в список глобальных посредников в вашем HTTP-ядре.

При вызове метода PHPterminate() в посреднике, Laravel получит свежий экземпляр посредника из сервис-контейнера. Если вы хотите использовать тот же самый экземпляр посредника при вызовах методов PHPhandle() и PHPterminate(), зарегистрируйте посредника в контейнере при помощи метода PHPsingleton().

Комментарии (3)

potMaster

Не совсем понятно про посредников «до» и «после». У них имена просто должны начинаться с «Before» и «After» соответственно ?

IceJOKER

Внимательно посмотрите на тело метода, в одном сначала идет выполнение кода, а потом передаем дальше, а во втором сначала передаем дальше, а потом выполняем код. http://joxi.ru/xAee68Wt57Q6Ay - на скрине, думаю, будет чуть понятнее

nko

Действительно сбивает заголовок «Посредник «до» и «после»» а после него

PHPclass BeforeMiddleware
...
PHPclass AfterMiddleware
...
У меня возникло недопонимание которое решилось после прочтения комментариев.

Может быть лучше переименовать заголовок «Посредник «до» и «после»» в «момент срабатывания посредника», а фразу «Момент, в который сработает посредник — до или после запроса, зависит от него самого.»
на «Момент, в который сработает посредник указывается в PHPfunction handle. И если нам необходимо выполнить действия до запроса, то необходимо их выполнить перед PHP$response $next($request);»

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.