學前必備知識點:閉包(Closure),array_reduce(),array_reverse()
可選進階知識點:裝飾者模式
簡易模擬請求處理管道
<?php
/**
* Interface Step
*/
interface Step {
/**
* @param Closure $next
* @return mixed
*/
public static function go(Closure $next);
}
/**
* 中介軟體1
* Class FirstStep
*/
class FirstStep implements Step {
/**
* @param Closure $next
*/
public static function go (Closure $next)
{
echo "開啟session,獲取資料...".'<br>';
$next();
echo "儲存資料,關閉SESSION...".'<br>';
}
}
/**
* 中介軟體2
* Class SecondStep
*/
class SecondStep implements Step {
/**
* @param Closure $next
*/
public static function go(Closure $next)
{
echo "檢測使用者許可權";
$next();
}
}
/**
* array_reduce自定義函式
* @param $step
* @param $className
* @return Closure
*/
function goFun($step, $className)
{
return function() use($step,$className)
{
return $className::go($step);
};
}
/**
* 模擬執行處理管道
*/
function then()
{
$steps = ["FirstStep","SecondStep"];
$prepare = function() { echo "請求向路由器傳遞,返回響應...".'<br>';};
$go = array_reduce($steps,"goFun",$prepare);
//這裡是關鍵,第一個是要處理的陣列,第二個是自定義回撥函式,
//第三個是可選引數,為初始化引數,被當作array_reduce中第一個值來處理,若陣列為空則作為返回值。
//var_dump($go);
//$test = new Reflection($go);
$go();
}
then();
/*
* 詳細解析
* 定義步驟一,步驟二
* 定義初始化引數$preapres
* array_reduce執行過程:
* 1.生成閉包函式function()
{
FirstStep::go($prepares);
};
* 2.生成function()
{
SecondStep::go(function()
{
FirstStep::go($prepares);
};);
};
* 最終執行順序是每個類中的go方法:SecondStep,First的第一個步驟,$prepares,First的第二個步驟,可以看到與陣列['FirstStep,'SecondStep']的順序反過來了
* 在實際Laravel的管道中用了array_reverse,使得執行順序與陣列定義的順序一致
* 這裡看起來有點類似遞迴,先一層一層進入,再把執行權一層一層轉回去
在閉包中傳入閉包…..
執行閉包 , 在閉包的語句裡再執行傳入的閉包
* */
laravel中的請求處理管道
<?php
interface Middleware
{
public static function handle(Closure $next);
}
class VerifyCsrfToken implements Middleware
{
public static function handle(Closure $next)
{
echo "驗證csrf-token.......";
$next();
}
}
class ShareErrorsFromSession implements Middleware
{
public static function handle(Closure $next)
{
echo "如果session中有errors變數,共享他....";
$next();
}
}
class StartSession implements Middleware
{
public static function handle(Closure $next)
{
echo "開啟session,獲取資料....";
$next();
echo "儲存資料,關閉session..";
}
}
class AddQueuedCookiesToResponse implements Middleware
{
public static function handle(Closure $next)
{
$next();
echo "新增下一次請求需要的cookie...";
}
}
class EncryptCookies implements Middleware
{
public static function handle(Closure $next)
{
echo "對輸入請求的cookie進行解密...";
$next();
echo "對輸出響應的cookie進行加密...";
}
}
class CheckForMaintenanceMode implements Middleware
{
public static function handle(Closure $next)
{
echo "確定當前程式是否處於維護狀態...";
$next();
}
}
function getSlice()
{
return function ($stack, $pipe) {
return function () use ($stack, $pipe) {
return $pipe::handle($stack);
};
};
}
function then()
{
$pipes= [
"CheckForMaintenanceMode",
"EncryptCookies",
"AddQueuedCookiesToResponse",
"StartSession",
"ShareErrorsFromSession",
"VerifyCsrfToken"
];
$firstSlice = function () {
echo "請求向路由器傳遞,返回響應....";
};
$pipes = array_reverse($pipes);
call_user_func(
array_reduce($pipes, getSlice(), $firstSlice)
);
}
then();
/*
* 先reverse把陣列倒轉過來
* 於是先生成VerifyCsrfTokenLLhanle($firstSlice);
* 再生成ShareErrorsFromSession::handle($上一步生成的閉包);
* ......
* ....
* 最後生成CheckForMaintenanceMode::handle($上一步生成的閉包);
*
* 於是執行順序就變為腦圖
*
*/
本作品採用《CC 協議》,轉載必須註明作者和本文連結