解析laravel中间件实现

1,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〇()。这 里我们可以清晰地理解请求处理通道是如何设计出来的。笔者第一次接触这部分也是很难理 解,简化一下就显而易见了,所以复杂的东西之所以复杂是我们没有把它简化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值