中间件是什么?
每个中间件是一个定义了handle方法的类或是一个匿名函数,一般所有中间件放在同一个文件夹middleware中,方便管理public function handle($request, Closure $next)
中间件有什么用
一: 路由前中间件(也叫全局中间件)
这些中间件,在根据请求找到匹配的路由之前就开始执行
1.配置
// 在 \App\Http\Kernel::$middleware中定义,是一个数组,如
$middleware = [
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\App\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\App\Http\Middleware\TrustProxies::class,
];
// 在 \Zhiyi\Plus\Http\Kernel::$middleware的值为
$middleware = [
\Zhiyi\Plus\Http\Middleware\CrossDomain::class,
\Illuminate\Foundation\Http\Middleware\CheckForMaintenanceMode::class,
\Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
\Zhiyi\Plus\Http\Middleware\TrimStrings::class,
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
\Zhiyi\Plus\Http\Middleware\TrustProxies::class,
];
2.执行顺序
是按上下执行,这里面的中间执行完后,再执行\Illuminate\Foundation\Http\Kernel::dispatchToRouter()
框架内置的中间件放在Illuminate\Foundation\Http\Middleware下面,一共有6个
二: 路由中间件
这些中间件是在路由匹配之后,与当前匹配路由及控制器有关
1: 在控制器中定义
在控制器的构造函数中定义
public function __construct(){
$this->middleWare('auth');
$this->middleWare('log',['only'=>['show','detail']]);
}
覆盖getMiddleware()方法
public function getMiddleware(){
return ['auth','log',['middleware'=>'hello','options'=>['only'=>['index','show']]]];
}
2: 在路由中定义
在第二个参数中定义middleware
Route::get('/login',[
'uses'=>'LoginController@index',
'middleware'=>['abc','def']
])
直接给路由使用middleware()方法
Route::get('/login','')->middleware('中间件1','中间件2');//数组也行
在group中定义
Route::group(['middleware' => ['has-permission:access-dashboard']], function (Router $router) use ($adminRoute) {
...
});
为什么全局中间件是一个完整的类名,而路由中间件是键名或群组名
键名或群组名其实是对应一个中间件类,它们的对应关系在Kernel中定义,如
kernel中 $routeMiddleware 对应 router中 middleware属性
kernel中 $middlewareGroups 对应 router中 middlewareGroups属性
$routeMiddleware = [
别名 => 有handle方法的类名或匿名函数
'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' => \Zhiyi\Plus\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'ability' => \Zhiyi\Plus\Http\Middleware\UserAbility::class,
'sensitive' => \Zhiyi\Plus\Http\Middleware\DisposeSensitive::class,
'operation' => \Zhiyi\Plus\Http\Middleware\SensitiveOperation::class,
'wang' => function(){这是一个闭包}
];
$middlewareGroups = [
'web' => [
\Zhiyi\Plus\Http\Middleware\EncryptCookies::class,
\Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class,
\Illuminate\Session\Middleware\StartSession::class,
// \Illuminate\Session\Middleware\AuthenticateSession::class,
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
\Zhiyi\Plus\Http\Middleware\VerifyCsrfToken::class,
\Illuminate\Routing\Middleware\SubstituteBindings::class,
'api' //可以是另一组名,这样,如果指定的中间件中web,那么包括上面的和api组中合起来的所有中间件
'wang' // 也可以是$routeMiddleware中的一个别名(键名)
],
'api' => [
'throttle:120,1',// :前面是中间件名,:后面是参数
'bindings',
],
'admin' => [
'ability:admin: login,你没有权限访问后台。',
],
];
路由中间件在进入管道之前,会转为以下一个由完整类名组成的一维数组
Array(
[0] => Illuminate\Routing\Middleware\ThrottleRequests:120,1
[1] => Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse
[2] => Illuminate\Session\Middleware\StartSession
[3] => Illuminate\View\Middleware\ShareErrorsFromSession
[4] => Zhiyi\Plus\Http\Middleware\VerifyCsrfToken
[5] => Illuminate\Routing\Middleware\SubstituteBindings
)
中间件的格式
- 别名
$this->middleWare(‘auth’); - 组名
$this->middleWare(‘api’)
- 闭包
$this->middleWare(function($request,$next){})
- 完整类名 $this->middleWare(IlluminateRoutingMiddlewareThrottleRequests)
三: 使用场景
全局中间件
new Pipeline($this->app))->send($request) ->through($this->middleware) ->then($this->dispatchToRouter())
路由中间件
new Pipeline($this->container))->send($request)->through($middleware)->then(
function ($request) use ($route) {
return $this->prepareResponse(
$request, $route->run()
);
}
);