Laravel 中间件提供了一种方便的机制来过滤进入应用的HTTP请求。在app/Http/Middleware文件夹中。
例如:Laravel 内置了一个中间件来验证用户的身份认证 ,如果没有通过身份认证,中间件会将用户重定向到登陆界面。中间件主要是对请求进行过滤的。(类似于门口保安,可以对进入车辆做检查拦截)。
现在来创建一个中间件:
使用artisan命令行工具:php artisan make:middleware CheckAge
该命令将会在app/Http/Middleware 目录内新建一个CheckAge 类。在文件中的handle方法里可以写验证逻辑,针对用户是否登录可以写如下代码:
注册中间件
全局中间件#
如果你想让中间件在你应用的每个HTTP请求期间运行,只需要在 app/Http/kernel.php 类中的$middleware 属性
里列出这个中间件类。
为路由分配中间件#
如果要为特定的路由分配中间件,首先应该在 app/Http/Kernel.php 文件内为该中间件指定一个键。默认情况下,
Kernel类的$routeMiddleware 属性包含Laravel 内置的中间件条目。要加入自定义的,只需要把它附加到列表后并为其分配一个自定义
键 即可,例如
…
// 在 App\Http\Kernel 类中
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
];
一旦在kernel中定义了中间件,就可使用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);
中间件组#
有时你可能想用单一的 键 为几个中间件分组。使其更容易分配到路由。可以使用Kernel类的$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(){
//
})->midlleware('web');
Route::group(['middleware'=>['web']],function(){
//
})
中间件参数#
中间件也可以接受额外的参数,例如,如果应用需要在运行特定操作前验证经过身份认证的用户是否具备给定的 角色 你可以新建一个 CleckRole
中间件,由它来接收 角色 名称作为附加参数。
附加的中间件参数应该在 $next 参数之后被传递:
<?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)) {
// 重定向...
}
return $next($request);
}
}
定义路由时通过一个: 来隔开中间名称和参数来指定中间件参数,多个参数就使用逗号分隔:
Route::put('post/{id}',function($id)
{
//
})->middleware('role:editor');
Terminable 中间件#
有时中间件可能需要在HTTP响应发送到浏览器之后处理一些工作。比如,Laravel 内置对的 [session] 中间件会在响应发送到
浏览器之后将会话数据写入存储器中,如果你在中间件中定义一个 terminate 方法,则会在响应发送到浏览器后自动调用:
<?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 文件的全局中间件中。
在你的中间件上调用terninate调用时,Laravel会从服务容器中解析
一个新的中间件实例,如果要在调用 handle和terminate 方法时
使用同一个中间件实例,就使用容器的singleton方法向容器注册中间件。