laravel源码学习之pipeline

请求处理管道

增加或减少功能需要重新组织相应过程,即实例化对象的顺序;Laravel框架是通过服务容器进行自动化实例化,
实例间的功能调用也是通过闭包函数完成的,这里我们为了简化,我们将通过静态函数来避免实例化过程,只
仿真通过闭包函数完成装饰者模式,实现请求的处理管道

在理解代码之前,先了解一下array_reduce

array_reduce

array_reduce — 用回调函数迭代地将数组简化为单一的值
说明
array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) : mixed

array_reduce()将回调函数callback迭代地作用到array数组中的每一个单元中,从而将数组简化为单一的值。

参数

array

输入的array

callback

    callback( mixed $carry , mixed $item ) : mixed

carry

携带上次迭代里的值; 如果本次迭代是第一次,那么这个值是 initial。

item

携带了本次迭代的值。

initial

如果指定了可选参数 initial,该参数将在处理开始前使用,或者当处理结束,数组为空时的最后一个结果。
返回值

返回结果值
initial参数,array_reduce()返回NULL

<?php

interface Middleware
{
    public static function handle(Closure $next);
}

class VerifyCsrfToken implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "verify Csr Token ".'<br>';
        $next();
    }
}

class ShareErrorFromSession implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "share it if the variable of 'error' is existing in SESSION" . '<br>';
        $next();
    }
}

class StartSession implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "starting a SESSION, Getting data" .'<br>';
        $next();
        echo "saving data, Closing a Session" .'<br>';
    }
}

class AddQueuedCookiesToResponse implements Middleware
{
    public static function handle(Closure $next)
    {
        $next();
        echo "adding a cookie for next request" .'<br>';
    }
}

class EncryptCookies implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "Decrypting Cookies for input request" .'<br>';
        $next();
        echo "Encrypt cookie for output response" .'<br>';
    }
}

class CheckForMaintenceMode implements Middleware
{
    public static function handle(Closure $next)
    {
        echo "checking the state of program is maintenance mode" .'<br>';   
        $next();    
    }
}

function getSlice()
{
    return function($stack, $pipe){
        return function() use ($stack, $pipe){
            return $pipe::handle($stack);
        };
    };
}

function then()
{
    $pipe = [
        "CheckForMaintenceMode",
        "EncryptCookies",
        "AddQueuedCookiesToResponse",
        "StartSession",
        "ShareErrorFromSession",
        "VerifyCsrfToken",
    ];
    $firstSlice = function(){
        echo "take request submit to router , and return the response".'<br>';
    };
    $pipe = array_reverse($pipe);
    call_user_func(
            array_reduce($pipe, getSlice(), $firstSlice)
        );
}
then();
输出
checking the state of programer is maintenance mode
Decrypting Cookies for input request
starting a SESSION, Getting data
share it if the variable of 'error' is existing in SESSION
verify Csr Token 
take request submit to router , and return the response
saving data, Closing a Session
adding a cookie for next request
Encrypt cookie for output response

上面实例代码的主要部分就是call_user_func(array_reduce($pipe, getSlice(), $firstSlice)部分的理解;这部分也是最晦涩、难理解的部分;
根据array_reduce()接口功能属性(文章前面已经详细给出),画图分析这部分程序执行过程;

首先得理解array_reduce这个接口的使用,从上图可知array_reduce执行完成后,最后返回的是一个包含了6层的闭包对象;
call_user_func执行的时候从最外面那一层开始执行,此时$pipe的值为CheckForMaintenanceMode也就是首先调用
CheckForMaintenanceMode类的静态方法handle(),所以我们看到的第一条输出是checking the state of programer is maintenance mode
执行$next()时,其实就是执行CheckForMaintenanceMode::handle()方法中传入的闭包对象;
从图中可知,CheckForMaintenanceMode::handle($stack)中的$stack值是包含5层的闭包对象,而此时$pipe的值为EncryptCookies;
即执行EncryptCookies::handle($stack)返回输出Decrypting Cookies for input request;
以此类推就可以很容易分析上述出输出结果;

猜你喜欢

转载自www.cnblogs.com/uneasy96/p/12149296.html
今日推荐