laravel 中間件使用了 Pipeline
- vendor\laravel\framework\src\Illuminate\Foundation\Http\Kernel.php
return (new Pipeline($this->app))
->send($request)
->through($this->app->shouldSkipMiddleware() ? [] : $this->middleware)
->then($this->dispatchToRouter());
- then 函數(shù)
public function then(Closure $destination)
{
$pipeline = array_reduce(
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
return $pipeline($this->passable);
}
- carry 函數(shù)
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if (is_callable($pipe)) {
return $pipe($passable, $stack);
} elseif (! is_object($pipe)) {
list($name, $parameters) = $this->parsePipeString($pipe);
$pipe = $this->getContainer()->make($name);
$parameters = array_merge([$passable, $stack], $parameters);
} else {
$parameters = [$passable, $stack];
}
return method_exists($pipe, $this->method)
? $pipe->{$this->method}(...$parameters)
: $pipe(...$parameters);
};
};
}
讓我們?nèi)サ舴种l件,創(chuàng)建一個簡單例子
定義管道執(zhí)行函數(shù)
function reducePipe($pipesFn, $initFn) {
return array_reduce($pipesFn, function($carry, $pipe) {
return function($data) use($carry, $pipe) {
return $pipe($data, $carry);
};
}, $initFn);
}
定義3個管道函數(shù) $pipes
$pipes = [];
foreach(range(1, 3) as $row) {
$pipes[] = function($data, $next) use($row) {
echo 'pipe-before' . $row . PHP_EOL;
$data->num += $row;
$data = $next($data);
echo 'pipe-hehind' . $row . PHP_EOL;
return $data;
};
}
定義初始化函數(shù) $init
$init = function($data) {
echo 'init start' . PHP_EOL;
var_dump($data);
echo 'init end' . PHP_EOL;
return 'init';
};
定義初始化數(shù)據(jù) $data
$data = new StdClass;
$data->num = 1;
執(zhí)行函數(shù)
$reduce = reducePipe($pipes, $init); // 獲取 array_reduce 后的函數(shù)
$result = $reduce($data);
var_dump($result); // 結果和每個$pipe的 return 有關,傳遞關系 init -> h1 -> h2 -> h3
- 執(zhí)行結果
pipe-before3
pipe-before2
pipe-before1
init start
object(stdClass)#5 (1) {
["num"]=>
int(7)
}
init end
pipe-hehind1
pipe-hehind2
pipe-hehind3
string(4) "init"
ps: 所以為了得到正確的執(zhí)行順序,需要
array_reverse($pipes)
翻轉數(shù)組
解析 array_reduce
的執(zhí)行過程
洋蔥模型 before3->before2->before1->init->behind1->hehind2->hebind3
- $reduce
function($data) use($carry, $pipe) {
return $pipe($data, $carry);
};
- $pipe
function($data, $next) use($row) {
echo 'pipe-before' . $row . PHP_EOL;
$data->num += $row;
$data = $next($data);
echo 'pipe-hehind' . $row . PHP_EOL;
return $data;
};
reduce1
$reduce1 = function($data) {
$row = 1;
echo 'pipe-before' . $row . PHP_EOL;
$data->num += $row;
// $next($data) $next == $init
echo 'init start' . PHP_EOL;
var_dump($data);
echo 'init end' . PHP_EOL;
$data = 'init';
echo 'pipe-hehind' . $row . PHP_EOL;
return $data;
};
reduce2
$reduce2 = function($data) use($reduce1) {
$row = 2;
echo 'pipe-before' . $row . PHP_EOL;
$data->num += $row;
// $next($data) $next == $reduce1
$data = $reduce1($data);
echo 'pipe-hehind' . $row . PHP_EOL;
return $data;
};
reduce3
$reduce3 = function($data) use($reduce2) {
$row = 3;
echo 'pipe-before' . $row . PHP_EOL;
$data->num += $row;
// $next($data) $next == $reduce2
$data = $reduce2($data);
echo 'pipe-hehind' . $row . PHP_EOL;
return $data;
};
執(zhí)行 reduce3
var_dump($reduce3($data));
執(zhí)行結果
與之前的相同
pipe-before3
pipe-before2
pipe-before1
init start
object(stdClass)#5 (1) {
["num"]=>
int(7)
}
init end
pipe-hehind1
pipe-hehind2
pipe-hehind3
string(4) "init"