middleware 原理

php_yt發表於2020-10-11

middleware 的原理就是「管道」。

管道 (pipe)

管道類似水淨化過程中的層層過濾。

middleware 原理

中介軟體的意思就是說,在接下來的邏輯之前,需要的操作。
例如江河之水我們不能直接喝,在輸出淨水之前有過濾細菌的機器。
那麼我們把輸出淨水的邏輯,封裝成一個匿名函式 $next,然後只需要這樣:

$next = function(){
    echo "輸出淨水";
}
$next2 = function($next){
    echo "過濾細菌";
    $next()
}
執行:
$next2()
輸出:
//過濾細菌
//輸出淨水

現在發現水裡有細沙,我們又引入了過濾細沙的機器,需要在目前過濾系統的之前執行。

$next3 = function($next2){
    echo "過濾細沙";
    $next2()
}
執行:
$next3();
輸出:
//過濾細沙
//過濾細菌
//輸出淨水

例項程式碼

$step1 = function ($next){
    echo "第一步:過濾小石頭".PHP_EOL;
    $next();
};

$step2=function ($next){
    echo "第二步:過濾細沙".PHP_EOL;
    $next();
};

$step3 = function ($next){
    echo "第三步:過濾細菌".PHP_EOL;
    $next();
};

$success = function (){
    echo "最後:輸出純淨水".PHP_EOL;
};


$callback = function ($next,$step) {
    return function () use ( $next, $step ) {
        return $step($next);
    };
};
$middleWares = [
    $step1,
    $step2,
    $step3
];

$middleWares=array_reverse($middleWares); //將陣列元素順序反轉

call_user_func(
    array_reduce($middleWares,$callback,$sucess)
);
//第一步:過濾小石頭 第二步:過濾細沙 第三步:過濾細菌 最後:輸出純淨水

array_reduce

array_reduce ( array $array , callable $callback [, mixed $initial = NULL ] ) : mixed
array_reduce() 將回撥函式 callback 迭代地作用到 array 陣列中的每一個單元中,從而將陣列簡化為單一的值。

解釋挺不容易明白,$array就是中介軟體陣列;$callback 見上面的 $callback 變數,永遠返回一個閉包函式;$initial 意思是 init 初始值,也就是最終的目的「輸出淨水」$success

模擬laravel中介軟體

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

class StartSession implements MiddleWare{
    public static function handle( Closure $next ) {
        echo '開啟 session'.'<br>';
        $next();
        echo '關閉 session'.'<br>';
    }
}
class AddQueuedCookiesToResponse implements MiddleWare{
    public static function handle( Closure $next ) {
        $next();
        echo '新增下一次請求的token'."<br>";
    }
}
class EbcryptCookies implements MiddleWare{
    public static function handle( Closure $next ) {
        echo '對 cookie 加密'.'<br>';
        $next();
        echo '對 cookie 解密'.'<br>';
    }
}


function getSlice(){
    return function ($stack,$pipe){
        return function () use ($stack,$pipe){
            return $pipe::handle($stack);
        };
    };
}
function then() {
    $pipes = [
        'EbcryptCookies',               //加密請求cookie
        'AddQueuedCookiesToResponse',   //新增下一次請求需要的cookie
        'StartSession',                 //開啟session
    ];

    $firstSlice=function(){echo '請求向路由器傳遞,返回相應'.'<br>';};

    $pipes=array_reverse($pipes);

    call_user_func(
        array_reduce($pipes,getSlice(),$firstSlice)
    );
}

then();
    /*
        對 cookie 加密
        開啟 session
        請求向路由器傳遞,返回相應
        關閉 session
        新增下一次請求的token
        對 cookie 解密
    */
本作品採用《CC 協議》,轉載必須註明作者和本文連結
focus

相關文章