middleware
- Global middleware
- Assign middleware to routes
- Middleware group
Introduction
Middleware provides a convenient mechanism to filter HTTP requests entering an application. For example, Laravel includes a middleware that verifies user authentication for your application. If the user is not authenticated, the middleware will redirect the user to the login interface. However, if the user is authenticated, the middleware will further allow the request to the application.
Of course, in addition to identity authentication, you can also write additional middleware to perform various tasks. For example: CORS middleware can be responsible for adding appropriate header information to all responses leaving the application; logging middleware can log all requests coming into the application.
Laravel comes with some middleware, including authentication, CSRF protection, etc. All these middlewares are located in the
app/Http/Middleware
directory.Define middleware
Create new ones by running the
make:middleware
Artisan command Middleware:php artisan make:middleware CheckAge
This command will create a new
CheckAge
class in theapp/Http/Middleware
directory. In this middleware, we only allowage
Requests with parameters greater than200
will access this route, otherwise, they will be redirected tohome
<?php 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); } }
As you can see, if If the specified
age
parameter is less than or equal to200
, this middleware will return an HTTP redirect to the client; otherwise, the request will be passed further to the application. To have the request continue to be passed to the application (i.e. allow the middleware to "pass" validation), just call the callback function$next
with$request
as the parameter.It's best to think of middleware as a series of
HTTP
requests that must be passed through to get to the "layer" of your application. Each layer checks the request to see if it meets certain criteria, and can even reject it entirely (before requesting access to your application) if it doesn't.{Tip} All middleware is passed through the service container, so you can type any dependencies you need in the constructor of your middleware.
Pre & post middleware
Middleware is executed before or after the request, depending on the middleware itself. For example, the following middleware will perform some task before the application handles the request:
<?php namespace App\Http\Middleware; use Closure;class BeforeMiddleware{ public function handle($request, Closure $next) { // Perform action return $next($request); } }
However, this middleware performs some task after the application requests
:<?php namespace App\Http\Middleware; use Closure; class AfterMiddleware{ public function handle($request, Closure $next) { $response = $next($request); // Perform action return $response; } }
Registration middleware
###If you want the middleware to run during every HTTP request your application handles. Just list this middleware in the
$middlewareattribute in
app/Http/Kernel.phpDistribute middleware for routing
Assuming that you want to distribute middleware for a specified route, you should first allocate a middleware for the middleware in the
app/Http/Kernel.php
file. key. By default, Laravel's built-in middleware is included under the$routeMiddleware
attribute in this class. To add a custom middleware, just append it to the list and assign it a custom key. For example:// 在 App\Http\Kernel 类中... 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, ];
Once the middleware is defined in the HTTP kernel, you can assign middleware to the route through the
middleware
method:Route::get('admin/profile', function () { // })->middleware('auth');
You can also assign middleware to the route Distributing multiple middleware:
Route::get('/', function () { // })->middleware('first', 'second');
When assigning middleware, you can also pass the full class name:
use App\Http\Middleware\CheckAge; Route::get('admin/profile', function () { // })->middleware(CheckAge::class);
Middle Component
Sometimes you may want to use a key to package multiple middleware into a group so that they can be easily applied to routes. You can use the
$middlewareGroups
attribute of Http Core.Laravel has built-in
web
andapi
middleware groups out of the box, which contain common middleware you may want to apply to Web UI and API routing:/** * 应用程序的路由中间件组 * * @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',], ];
Middleware groups can be assigned to route and controller actions using the same syntax as individual middleware. Likewise, middleware makes it easier to assign multiple middlewares to a route at once:
Route::get('/', function () { // })->middleware('web'); Route::group(['middleware' => ['web']], function () { // });
{Tip}
RouteServiceProvider
defaults to theweb
middleware group Automatically applied toroutes/web.php
.Sorting Middleware
Rarely, you may need middleware to They are executed in a specific order, but you have no control over their order when they are assigned to routes. In this case, the middleware priority can be specified using the
$middlewarePriority
attribute of theapp/Http/Kernel.php
file:/** * 中间件的优先级排序列表 * * 将会强制非全局中间件始终保持给定的顺序。 * * @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,];
Middleware parameters
Middleware can also receive other parameters. For example, if your application needs to verify that the user is a given "role" before performing a given action, you can create a
CheckRole
middleware that receives the "role" name as an additional parameter .Additional intermediate parameters should be passed to the middleware after the
$next
parameter:<?php namespace App\Http\Middleware; use Closure;class CheckRole{ /** * 处理传入的参数 * * @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); } }
Separate the middle by a
:
when defining the route Use the file name and parameters to specify middleware parameters. Use commas to separate multiple parameters:Route::put('post/{id}', function ($id) { // })->middleware('role:editor');
Terminable Middleware
Sometimes, middleware may need to do some work after preparing the HTTP response. For example, Laravel's built-in "session" middleware writes session data to storage when the response is fully ready. If you define a
terminate
method on your middleware, it will be called automatically after the response is ready to be sent to the browser.<?php 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
The method should receive both the request and the response. After defining this middleware, don't forget to add it to the route list or the global middleware of theapp/Http/Kernel.php
file.When you call the
terminate
method on middleware, Laravel will resolve a new middleware instance from the service container. If you are using the same middleware instance while calling thehandle
andterminate
methods, use the container'ssingleton
method to register the middleware in the container.