laravel中间件介绍
HTTP 中间件为过滤进入应用的 HTTP 请求提供了一套便利的机制。例如,Laravel 内置了一个中间件来验证用户是否经过授权,如果用户没有经过授权,中间件会将用户重定向到登录页面,否则如果用户经过授权,中间件就会允许请求继续往前进入下一步操作。
当然,除了认证之外,中间件还可以被用来处理更多其它任务。比如:CORS 中间件可以用于为离开站点的响应添加合适的头(跨域);日志中间件可以记录所有进入站点的请求。
Laravel框架自带了一些中间件,包括维护模式、认证、CSRF 保护中间件等等。所有的中间件都位于app/Http/Middleware 目录。
上面是laravel的中间件介绍,通俗来讲中间件就是控制器在执行一个操作前后,我们可以预先或者执行完后再执行的事情,分别对应是前置中间件,后置中间件。
前置中间件:在控制器执行前做的操作。
前置中间件在我们laravel应用中,常用到的场景有检查用户时候登录,给api访问加权限等等,这些都是可以放在前置中间件里面,而我们的控制器则专注与业务的实现,控制器前置需要执行的一些检查方法都可以放在前置中间件。
后置中间件:在控制器执行完后做的操作。
后置中间件在我们的laravel应用中,常用场景可以是记录控制器操作完后的系统日志等等,一些需要在操作执行完毕后行为和动作都可以放在后置中间件。
2,laravel中间件设计模式--装饰者模式
首先来看看什么叫装修者模式,这里举个例子,某一天韩梅梅准备和李雷出门看电影,在韩梅梅出门前需要仔细打扮一番,首先韩梅梅需要从衣柜挑选一件美丽漂亮的长裙,然后再从鞋柜里面选择一双合适的高跟鞋,再然后花一点淡妆,就可以出门了。所以对于韩梅梅来说,挑选衣服,挑选鞋子,化妆这三件事情就是用来装饰自己的。韩梅梅就是被装饰着,衣服,鞋子,化妆就是装饰的内容。首先我们来看看面向过程的代码我们怎么写:
function HanMeiMei(){ chooseSkirt();//挑选裙子 chooseShoes();//挑选鞋子 makeUp();//化妆 goOut();//出门 }
传统面向过程的方式我们会一一写好相关函数,然后按照顺序调用,直到韩梅梅出门这件事情。想想如果韩梅梅是个程序媛,韩梅梅肯定会觉得这种方式,不方便后期业务上的改动,比如韩梅梅在挑选裙子,鞋子,化妆后,还需要挑选一个LV或者古驰的手提包,那么我们肯定是要去改整个程序流程,这对于后期频繁变动的需求改动起来是非常麻烦的。于是这里就引出了我们的设计模式--装饰者模式,装饰者模式解决的问题就是应用这些改动可以做到低耦合,不用改动太多的代码结构,实现在执行真正操作前,可以调整需要做的内容顺序或者添加额外的内容。有了装饰者模式后,韩梅梅对代码重构了:
首先定义公用接口
interface DecoratorOne{ public function display(); }
定义该接口的目的是为了后续所有的装饰物,比如裙子,鞋子,化妆等等都继承并实现该方法
然后韩梅梅实现该接口
class HamMeiMei implements DecoratorOne { public function display() { echo '我出门了'; } }
此类韩梅梅是被装饰者,实现接口display方法
创建一个实现接口且公共修饰物基本类
class finery implements DecoratorOne{ private $component; public function __construct(DecoratorOne $decoratorOne) { $this->component = $decoratorOne; } public function display() { $this->component->display(); } }
构造函数传入韩梅梅对象,此类就是后续所有装饰物,裙子,鞋子等等的parent,所有类继承该类,且所有装饰物都调用parent::display(),而display永远是来自构造方法里面的韩梅梅。意思是,不管韩梅梅添加多少装饰类,永远韩梅梅才是最后执行要做的行为就是出门。
所有的修饰物继承基本类且调用基本类的parent::display()
class shoes extends finery{ public function display() { echo "我穿上了shoes"; parent::display(); // TODO: Change the autogenerated stub } } class clothes extends finery{ public function display() { echo "我穿上了衣服"; parent::display(); // TODO: Change the autogenerated stub } }
都继承finery基本类,且调用parent::display()
实例化韩梅梅且加入修饰类
$HamMeiMei = new HamMeiMei(); $shoes = new shoes($HamMeiMei); $clothes = new clothes($shoes); $clothes->display();
通过调用韩梅梅和装饰类达到装饰效果。
除此之外,还可以创建一个数组用来保存需要执行的类,具体细节不细讲,有时间可以看看如下代码:
<?php /** * Created by PhpStorm. * User: wg * Date: 18-6-26 * Time: 上午11:31 */ interface IDecorator { public function before(); public function after(); } class Shoes implements IDecorator { private $size; public function __construct($size) { $this->size = $size; } public function after() { echo "我脱了 $this->size 码的鞋子,"; } public function before() { echo "我穿上 $this->size 码的鞋子,"; } } class Clothes implements IDecorator { private $color; public function __construct($color) { $this->color = $color; } public function before() { echo "我穿上了$this->color 颜色的衣服,"; } public function after() { echo "我脱了$this->color 颜色的衣服,"; } } class Tom { private $thing; public function goOut(){ $this->beforeGoOut(); echo "我出门了"; $this->afterGoOUt(); } public function beforeGoOut(){ foreach ($this->thing as $value){ $value->before(); } } public function afterGoOUt(){ $temp = array_reverse($this->thing); foreach ($temp as $item) { $item->after(); } } public function addThing(IDecorator $decorator){ $this->thing[] = $decorator; } } $tom = new Tom(); $tom->addThing(new Clothes('红')); $tom->addThing(new Shoes('40')); $tom->goOut();
3,laravel实现的中间件
<?php require_once __DIR__.'/vendor/autoload.php'; interface Middleware{ public static function go(Closure $next); } class testOne implements Middleware{ public static function go(Closure $next) { echo "测试一"; $next(); // TODO: Implement handle() method. } } class testTwo implements Middleware{ public static function go(Closure $next) { echo "测试二"; $next(); } } function goFun($step,$className){ return function () use ($step,$className){ return $className::go($step); }; } function thenTwo(){ $steps = ['testOne']; $prepare = function (){ echo "我是要做的操作"; }; $go = array_reduce($steps,'goFun',$prepare); $go(); } thenTwo();
整个程序比较难理解的是array_reduce($steps, ”goFun”,$prepare)函数和 goFun($step,SclassName)函数,其中 array_reduce()函数在参数手 册中介绍是用冋调函数迭代地将数组内容进行处理,共有三个参数,前两个参数是必须赋值 的,第一个是要处理的数组,第二个是处理函数名称或回调函数,第三个参数为可选参数, 为初始化参数,将被当做数组中第一个值来处理,如果数组为空则作为返回值。这里我们 给第三个参数传递一个回调函数,该函数用于将请求向路由器继续传递,返回响应,而第一 个参数为一个数组,该数组记录了外层功能的类名,goFun()函数作为处理数组的回调函数^ array_reduce()最终返冋的是一个回调函数,即$go,代码如下: $go = function () { return $ Firs tStep: : go (function () {echo ” 请求向路山器传递,返回响应 ".,
,;}); }; 在前面的例子中,通过call_user_flinc()函数执行这个回调函数,其实就相当于$8〇()。这 里我们可以清晰地理解请求处理通道是如何设计出来的。笔者第一次接触这部分也是很难理 解,简化一下就显而易见了,所以复杂的东西之所以复杂是我们没有把它简化。
评论 (0)