一个网站必须过滤进入应用程序的 HTTP 请求和权限检测,比如用户登录,用户是否有权限操作这个界面,菜单显示判断。在 ThinkPHP 里,往往通过继承一个基类,在初始化方法里调用检测方法,而Laravel 提供了中间件来验证身份或重定向,还可以负责为添加响应头或记录所有传入应用的请求。
中间件使用 make:middleware 命令生成,放在 app\Http\Middleware 下。所有的中间件都是通过 服务容器 解析的,因此,可以在构造函数中键入需要的任何依赖。
<?php
namespace App\Http\Middleware;
use Closure;
class AdminLogin
{
/**
* 处理传入的请求
*/
public function handle($request, Closure $next)
{
if(!session('user'))
{
return redirect('admin/login');
}
return $next($request);
}
}
上面就是一个最简单的中间件,Laravel将进入应用的请求对象传递给 Http Kernel 的 handle 方法,处理流入应用的请求对象 $request 并返回响应对象 $next。这里我检查了session里是否存在user数据,没有就重定向到登录界面,也可以对传入参数进行检测。
if ($request->id < 1)
{
return redirect('home');
}
中间件默认是在 请求前 执行,也可以使用后置中间件。
<?php
namespace App\Http\Middleware;
use Closure;
class AfterMiddleware
{
public function handle($request, Closure $next)
{
$response = $next($request);
// 执行动作
return $response;
}
}
中间件需要 注册 才能使用,如果想要添加自己的中间件,需要将相应的中间件类添加到app/Http/Kernel.php 的数组属性 $routeMiddleware 中,并且指定一个名称。
<?php
namespace App\Http;
use Illuminate\Foundation\Http\Kernel as HttpKernel;
class Kernel extends HttpKernel
{
/**
* 应用的路由中间件列表
*/
protected $routeMiddleware = [
'admin.login' => \App\Http\Middleware\AdminLogin::class,
];
然后在 路由 或者 路由组 里调用。
Route::get('/index', function () {
//
})->middleware('admin.login');
Route::group(['middleware' => ['admin.login']], function () {
//
});
如果想要定义的中间件在 每一个 HTTP 请求 时都被执行,只需要将相应的中间件类添加到数组属性 $middleware 中。
protected $middleware = [
\App\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,
];
可以将相关中间件打包到一个组里,Laravel 自带了 web 和 api 两个中间件组,分别包含可以应用到 Web 和 API 路由的通用中间件。
/**
* 应用程序的路由中间件组
*/
protected $middlewareGroups = [
'login' => [
\App\Http\Middleware\AdminLogin::class,
],
];
中间件主要过滤 非法check 和 权限验证,有些人把表单请求字段验证甚至数据库相关check,也写在中间件里,我觉得是不对的,应该放在控制器中的 validate 方法中。