PHP閉包Closureとarray_reduce結合の一例
8455 ワード
最近laravel 5を研究しています.5のソースコード、その中の1段のコードを発见してとても面白いと感じます!
ファイル:vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php
このコードは最初は迷っていたように見えますが、以下のdemo分解を行います.
出力:
ファイル:vendor/laravel/framework/src/Illuminate/Pipeline/Pipeline.php
public function then(Closure $destination)
{
$pipeline = array_reduce(
array_reverse($this->pipes), $this->carry(), $this->prepareDestination($destination)
);
return $pipeline($this->passable);
}
protected function carry()
{
return function ($stack, $pipe) {
return function ($passable) use ($stack, $pipe) {
if (is_callable($pipe)) {
// If the pipe is an instance of a Closure, we will just call it directly but
// otherwise we'll resolve the pipes out of the container and call it with
// the appropriate method and arguments, returning the results back out.
return $pipe($passable, $stack);
} elseif (! is_object($pipe)) {
list($name, $parameters) = $this->parsePipeString($pipe);
// If the pipe is a string we will parse the string and resolve the class out
// of the dependency injection container. We can then build a callable and
// execute the pipe function giving in the parameters that are required.
$pipe = $this->getContainer()->make($name);
$parameters = array_merge([$passable, $stack], $parameters);
} else {
// If the pipe is already an object we'll just make a callable and pass it to
// the pipe as-is. There is no need to do any extra parsing and formatting
// since the object we're given was already a fully instantiated object.
$parameters = [$passable, $stack];
}
return method_exists($pipe, $this->method)
? $pipe->{$this->method}(...$parameters)
: $pipe(...$parameters);
};
};
}
このコードは最初は迷っていたように見えますが、以下のdemo分解を行います.
// array_reduce
$a = array( 1 , 2 , 3 , 4 , 5 );
$b = array_reduce ( $a , function($v , $w){
return function($p) use($v, $w){
var_dump($v);
};
} );
if(is_callable($b)){
$b('spring');
}
出力:
object(Closure)#5 (2) {
["static"]=>
array(2) {
["v"]=>
object(Closure)#4 (2) {
["static"]=>
array(2) {
["v"]=>
object(Closure)#3 (2) {
["static"]=>
array(2) {
["v"]=>
object(Closure)#2 (2) {
["static"]=>
array(2) {
["v"]=>
NULL
["w"]=>
int(1)
}
["parameter"]=>
array(1) {
["$p"]=>
string(10) ""
}
}
["w"]=>
int(2)
}
["parameter"]=>
array(1) {
["$p"]=>
string(10) ""
}
}
["w"]=>
int(3)
}
["parameter"]=>
array(1) {
["$p"]=>
string(10) ""
}
}
["w"]=>
int(4)
}
["parameter"]=>
array(1) {
["$p"]=>
string(10) ""
}
}