17.1 什么是中间件

中间件就是当程序接收HTTP 请求时,拦截后进行过滤和处理;

比如当用户登录时,可以通过中间件进行验证比对,错误后让其跳转到登录页面;

框架系统自带了一些中间件,比如之前CSRF 令牌保护,就是中间件实现的;

17.2 中间件的基本使用

系统默认创建了几个中间件,它们在 app\Http\Middleware 中。

1、自定义中间件(前置中间件)

如果创建一个自定义的中间件?可以通过一句命令创建一个check 中间件;

  1. php artisan make:middleware Check //创建一个名为Check的中间件

此时,我们打开创建好的Check 中间件文件,默认有一个handle的方法,关于该方法,解释如下:

//Handle an incoming request.
//方法名和格式,是固定的。默认的这两个参数,必须存在
public function handle(Request $request, Closure $next)
{
    //可以在这里写自己的验证、跳转方法
    ......

    //固定返回格式,让其继续往下执行
    return $next($request);
}

接下来,需要对中间件进行注册,才可以在路由上使用。

打开 Http/Kernel.php文件,在路由配置中间件的区域进行注册:

    protected $routeMiddleware = [
        //自己添加自定义的中间件
        'check' => Check::class,    //这种写法,是在最前面有:use App\Http\Middleware\Check;
        //下面是系统默认有的中间件
        'auth' => \App\Http\Middleware\Authenticate::class,
        ......
    ];

接下来,可以在前面的 handle方法 中,写入验证内容:

//方法名和格式,是固定的。默认的这两个参数,必须存在
public function handle($request, Closure $next)
{
    //可以在这里写自己的验证、跳转方法
    //我们模拟测试,假如登录的id不是1
    if ($request->get('id') != 1) {
        //跳转至登录页面
        return redirect(url('/login'));
    }
    //固定返回格式,让其继续往下执行
    return $next($request);
}

然后,我们就可以在其他的页面,比如后台页面的路由上,添加中间件,进行验证:

Route::get('/admin','LoginController@index')->middleware('check');

上面这种中间件,属于前置中间件,也就是先拦截Http 请求,再执行主体代码。

2、后置中间件

另一种,就是后置中间件,也就是先执行主体代码,再拦截处理;

//固定方法,固定格式
public function handle($request, Closure $next)
{
    //先执行主体代码
    $response = $next($request);

    //再进行拦截 Http 请求,做相应处理
    echo '我是后置中间件';

    //固定格式返回
    return $response;
}

3、其他方法

1、在路由中间件,我们可以设置多个中间件,进行调用:

Route::get('/admin','LoginController@index')->middleware('check', 'auth');

2、如果没有在 Http/Kernel.php 配置文件中注册中间件,可以采用完整的类名来进行调用:

Route::get('/admin','LoginController@index')->middleware(\App\Http\Middleware\Check::class);

3、全局中间件:直接配置在Http/Kernel.php 配置文件中的$middleware属性下,每次执行都必然调用:

//These middleware are run during every request to your application.
protected $middleware = [
     //添加自定义的全局中间件
     \App\Http\Middleware\Every::class,
    //下面是系统自带的默认的全局中间件
    // \App\Http\Middleware\TrustHosts::class,
    \App\Http\Middleware\TrustProxies::class,
    \Fruitcake\Cors\HandleCors::class,
    ......
 ];

4、中间件的核心方法可以有第三个参数,可以在控制器调用时传递;

比如前面的handle方法,可以写为:

//Handle an incoming request.
//方法名和格式,是固定的。默认的这两个参数,必须存在
public function handle(Request $request, Closure $next, $param)
{
    //可以在这里写自己的验证、跳转方法
    echo $param;
    ......

    //固定返回格式,让其继续往下执行
    return $next($request);
}

然后,在路由中,可以给中间件传递参数

Route::get('/admin','LoginController@index')->middleware('check:abc');

将输出abc

5、中间件组:如果有一些需要固定调用多个中间件,我们可以将它群组

protected $middlewareGroups = [
    'mymd' => [
        'check'=>\App\Http\Middleware\Check::class,
    ],
];

6、中间件中可以增加terminate()方法,在中间件响应完之后(return $next),再调用;

public function terminate($request, $response)
{
    echo '<br>Http 响应完毕之后再调用我';
}

7、中间件也可以在控制器的构造方法里调用:

public function __construct()
{
    $this->middleware('check:abc');
}

这里注意错误跳转会死循环;

以上。