laravel中间件
定义一个中间件
- 使用 make:middleware 命令来创建新的中间件。
php artisan make:middleware CheckAge //该命令会在 app/Http/Middleware 目录下生成新的 CheckAge 类
<?php
namespace App\Http\Middleware;
use Closure;
class CheckAge
{
/* */
public function handle($request, Closure $next)
{
if ($request->age <= 200) {
return redirect('home');//这个中间件中,我们仅允许 age 参数大于 200 的请求对路由进行访问,否则将重定向到 home 页面
}
return $next($request);
}
}
前置 & 后置中间件
中间件是在请求之前或之后执行,取决于中间件本身。例如,下面的中间件将在应用处理请求 之前 执行一些任务:
<?php
class BeforeMiddleware
{
public function handle($request, Closure $next)
{
// 执行一些任务
return $next($request);
}
}
然后,下面中间件是在应用请求 之后 执行一些任务:
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 执行一些任务
return $response;
}
}
注册中间件
全局中间件
如果你希望中间件在应用处理每个 HTTP 请求期间运行。只需要在 app/Http/Kernel.php 中的 $middleware 属性中列出这个中间件。
为路由分配中间件
假设你想为指定的路由分配中间件 ,首先应该在 app/Http/Kernel.php 文件内为该中间件分配一个键。默认情况下,该类中的 $routeMiddleware 属性下包含了 Laravel 内置的中间件。若要加入自定义的中间件,只需把它附加到列表后并为其分配一个自定义键。例如:
/ 在 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,
];
使用中间件
- 一旦在 HTTP 内核中定义好了中间件,就可以通过 middleware 方法将为路由分配中间件:
Route::get('admin/profile', function () { })->middleware('first','second'); //路由中使用中间件
Route::get('admin/profile', function () { })->middleware(CheckAge::class); // 分配中间件时,还可以传递完整的类名
Route::group(['prefix' => 'user',['middleware' => ['web']], function () { }); // 可以在路由群组中用中间件
中间件组
某些时候你可能希望使用一个键把多个中间件打包成一个组,以便更容易地分配给路由。你可以使用 Http 核心的 $middlewareGroups 属性。
Laravel 内置了开箱即用的 web 和 api 中间件组,其中包含你可能希望应用于 Web UI 和 API 路由的常用中间件:
/**
* 应用程序的路由中间件组
*
* @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 () {});
排序中间件
很少情况下,你可能需要中间件以特定的顺序执行,但是当它们被分配到路由时,你无法控制它们的顺序。在这种情况下,可以使用 app/Http/Kernel.php 文件的 $middlewarePriority 属性指定中间件优先级:
/**
* 中间件的优先级排序列表
* 将会强制非全局中间件始终保持给定的顺序。
* @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 参数之后传递给中间件:
<?php
namespace App\Http\Middleware;
use Closure;
class CheckRole
{
/**
* 处理传入的参数
*/
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');
Terminable 中间件
有时,在准备好 HTTP 响应之后,中间件可能需要做一些工作。例如,Laravel 内置的「session」 中间件会在完全准备好响应后将会话数据写入存储。如果你在中间件上定义了一个 terminate 方法,并且你使用的是 FastCGI ,那么它将会在响应准备发送到浏览器之后自动调用。
<?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 方法应该同时接收请求和响应。定义了这个中间件之后,别忘了将它添加到路由列表或者 app/Http/Kernel.php 文件的全局中间件中。
当你在中间件上调用 terminate 方法的时候, Laravel 将从 服务容器中解析出一个新的中间件实例。如果在调用 handle 和 terminate 方法的同时使用相同的中间件实例,请使用容器的 singleton 方法在容器中注册中间件
composer require fideloper/proxy // 设置信任代理有关的中间件