Laravel学习笔记基础系列--(九)详解Laravel中间件的快速使用

作者: 温新

分类: 【Laravel】

阅读: 1745

时间: 2021-07-06 14:20:39

作者:温新

时间:2021-06-25

什么是Laravel中间件

简而言之,Laravel中间件就是一套过滤所有HTTP请求的机制。一个请求到达控制器方法前要经过中间件,因此,在中间件这个位置就可以对请求进行过滤。

白话理解中间件:

  • 1、一个HTTP请求(URL)发起时,经过路由之后会被分发到中间件,中间件这里就可以拦截路由进行判断,符合要求才会允许访问路由对应的方法。

1571678055118516.png

  • 2、听起来还是有些懵,下面举个例来理解。

    一个房子所对应进出房子的大门,你是房子的主人,你下班回家,到了门口掏出钥匙,门锁就会判断你这个钥匙是不是我这把锁的钥匙,如果是,门锁就会放行,打开门,让你进去,进入家后,想干嘛就干嘛。如果门锁验证你的钥匙不对,就会发出在中间件中定义好的操作,比如,年轻人,你这把钥匙不是我这把锁的,哪来就回哪去吧。

    再来梳理一下这个流程,你就是用户,你拿起钥匙开锁就是发起一个请求,门锁就是中间件,判断你这个钥匙对不对,验证钥匙通过过,打开门就是对应的控制器方法。验证不通过就对应着我们在中间件所定义的操作。

快速使用中间件

用法:php artisan make:middleware 中间件名称

生成文件位置:app/Http/Middleware

第一步:创建中间件

php artisan make:middleware DemoCheck

该命令会在app/Http/Middleware目录下生成一个DemoCheck的类文件,这就是中间件文件,且是一个前置中间件。

第二步:编写中间件逻辑

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(152, 26, 26)"><?</span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">namespace</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">App\Http\Middleware</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Closure</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">use</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Illuminate\Http\Request</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">DemoCheck</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">handle</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Closure</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">testId</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">></span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">20</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">            <span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">redirect</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'/'</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

代码解释:如果接收到的参数testId大于20,那么就阻止路由继续往下走到控制器方法,并返重定向到首页。若testId参数小于20,则通过调回函数$next()将请求继续往下传递。

第三步:注册中间件

中间件分类三类:全局中间件、中间件组、指定路由中间件。这个案例中使用路由中间件。

全局中间件的注册需要在app/Http/Kernel.php中的$middleware数组属性中进行。

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// app/Http/Kerner.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">protected</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$routeMiddleware</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> [</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'testId'</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">=></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">\App\Http\Middleware\DemoCheck</span>::<span style="box-sizing: border-box;color: rgb(119, 0, 136)">class</span>,</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">];</span>

到这里,中间件使用就可以使用了。

第四步:定义路由器

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// web.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Route</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">get</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'demo/{testId}'</span>, <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'DemoController@index'</span>)<span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">middleware</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'testId'</span>);</span>

由于注册的是路由中间件,因此定义的中间件一定要定义到具体的路由上。

前置/后置中间件

前置中间件

如上中间件的快速使用,使用的是前置中间件。

什么是前置中间件?前置中间件,请求没有到达所对应的控制器方法就被拦截了。举个不恰当的例子,一个入室盗窃的小偷,刚要拿出撬门的工具时就被警察叔叔给抓住了。

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// DemoCheck.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">handle</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Closure</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 前置中间件</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 这里写处理逻辑</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

主要注意的是,使用前置中间件时,如使用$request->all()接收用户参数的方法是无效的,是接收不到用户参数的。

后置中间件

什么是后置中间件后置中间件,就是请求会到达所对应的控制器的具体方法。举个不恰当的例子,一个入室盗窃的小偷,已经撬门而入且得手了贵重物品,刚出门口就被警察叔叔给抓了。

改造中间件为后置请求:

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// DemoCheck.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">handle</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Closure</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$response</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">=</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 后置中间件</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">if</span> (<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">testId</span> <span style="box-sizing: border-box;color: rgb(152, 26, 26)">></span> <span style="box-sizing: border-box;color: rgb(17, 102, 68)">20</span>) {</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">        <span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(0, 0, 0)">redirect</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'/'</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    }</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(119, 0, 136)">return</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$response</span>;</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

改造控制器方法

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// DemoController.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">store</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 0, 0)">dd</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span><span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">all</span>());</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}  </span>

访问路由你的域名/demo/1111,路由中携带testId=1111,此时是大于20的,它首先会被重定向到首页吗?答案是它先打出控制器方法中的数据,然后才被重定向后首页,这就是后置中间件。

前置与后置中间件怎么用?请参考 轻松使用Laravel6中间件 这篇文章。

中间件传递参数

用法 :Route::get()->middleware('中间件名:参数')

注意:若有多个参数,则使用逗号分隔,如middleware('testId:参数1,参数2')

中间件可以携带参数。此处的参数不是用户参数,而是由开发人员所指定的附加参数,常用于判断用户权限。

下面基于最开始所使用的后置中间件案例,开始改造:

修改路由。中间件参数接收的是值,而不是键。

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// web.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(0, 0, 0)">Route</span>::<span style="box-sizing: border-box;color: rgb(0, 0, 0)">get</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'demo/{testId}'</span>, <span style="box-sizing: border-box;color: rgb(170, 17, 17)">'DemoController@index'</span>)<span style="box-sizing: border-box;color: rgb(152, 26, 26)">-></span><span style="box-sizing: border-box;color: rgb(0, 0, 0)">middleware</span>(<span style="box-sizing: border-box;color: rgb(170, 17, 17)">'testId:id,name'</span>);</span>

修改中间件

<span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(170, 85, 0)">// DemoCheck.php</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box"></span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px"><span style="box-sizing: border-box;color: rgb(119, 0, 136)">public</span> <span style="box-sizing: border-box;color: rgb(119, 0, 136)">function</span> <span style="box-sizing: border-box;color: rgb(0, 0, 255)">handle</span>(<span style="box-sizing: border-box;color: rgb(0, 0, 0)">Request</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$request</span>, <span style="box-sizing: border-box;color: rgb(0, 0, 0)">Closure</span> <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$next</span>, <span style="box-sizing: border-box;color: rgb(0, 85, 170)">$id</span>,<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$name</span>)</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">{</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 打印中间件参数</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 0, 0)">dump</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$id</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(0, 0, 0)">dd</span>(<span style="box-sizing: border-box;color: rgb(0, 85, 170)">$name</span>);</span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">    <span style="box-sizing: border-box;color: rgb(170, 85, 0)">// 此处为了节约篇幅,省略后面代码</span></span><br></br><span style="box-sizing: border-box;padding-right: 0.1px">}</span>

我是温新

每天进步一点点,就一点点

请登录后再评论