PHP代码求详解?

贴一段在知乎上看到的代码, 想了很久还是没想通, 求大神通俗讲解:

<?php

namespace App;

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

class Session implements Middleware
{
    public function handle($next)
    {
        echo "<br/>Session Start<br/>";
        $next();
        echo "<br/>Session End<br/>";
    }
}

class Mysql implements Middleware
{
    public function handle($next)
    {
        echo "<br/>Mysql Start<br/>";
        $next();
        echo "<br/>Mysql end<br/>";
    }
}

function run($next, $step)
{
    return function () use ($next, $step) {
        call_user_func_array([new $step, 'handle'], [$next]);
    };
}

$class    = [Session::class, Mysql::class];
$callback = array_reduce($class, 'App\run', function () {});
$callback();

运行结果

Mysql Start

Session Start

Session End

Mysql end

请输入代码
阅读 2k
1 个回答

跟下面这个问题一样,不重复写了。
https://segmentfault.com/q/10...

首先是这样的.我们看下面的代码来理解一下

<?php
function myfunction($v1,$v2)
{
return $v1+$v2;
}
$a=array(10,15,20);
print_r(array_reduce($a,"myfunction",5)); //50
?>

上面的结果为50.那么它的过程是怎么样的呢?我们对代码进行改良

function myfunction($v1, $v2)
{
    var_dump($v1, $v2);
    return $v1 + $v2;
}

$a = array(10, 15, 20);
print_r(array_reduce($a, "myfunction", 5)); //50
echo "\n";

然后可以看到如下输出

int(5)
int(10)
int(15)
int(15)
int(30)
int(20)
50

第一个v1 = 5,v2 = 10;
第二个v1 = 15 (前一个返回的值) , v2 = 15; $a[1]的值;
第三个v1 = 30 (上一次的返回值) , v2 = 20; $a[2]的值;



现在回答题主的问题:

上面的这个例子myfunction返回的是一个数值,但是题主的问题run方法返回的是一个function,这一点很重要。

现在我们把array_reduce($class, 'App\run', function () {});第三个函数看作是A

现在按照array_reduce方法的原理开始执行
第一步run(A, Session::class),返回函数B(特别重要,run方法知识返回一个函数,函数并不会执行)
第二步run(B, Mysql::class),返回函数C(此时函数C会赋值给$callback

array_reduce函数执行完毕最终返回的就是函数C,最后一行代码$callback();就是执行函数C。

现在开始反推

// 函数C如下,其中$next是函数B,$step是函数Mysql::class
function($next, $step) {
    call_user_func_array([new $step, 'handle'], [$next]);
};

// 转换一下就是
call_user_func_array([new Mysql, 'handle'], [B]);

// 就是把函数B作为参数传递给了Mysql的handle方法,$next就是函数B
public function handle($next)
{
    echo "<br/>Mysql Start<br/>";
    $next();
    echo "<br/>Mysql end<br/>";
}

// 此时就是会先输出<br/>Mysql Start<br/>,然后执行函数B,那函数B是什么呢?
// 函数B就是,A是一个空函数`function() {}`
call_user_func_array([new Session, 'handle'], [A]);

// 所以
echo "<br/>Session Start<br/>";
function() {};
echo "<br/>Session End<br/>";

// 此时函数B执行完毕,回到函数C,所以接着输出<br/>Mysql end<br/>

// 总结一下就是
echo "<br/>Mysql Start<br/>";
echo "<br/>Session Start<br/>";
function() {};
echo "<br/>Session End<br/>";
echo "<br/>Mysql end<br/>";

好了故事编完了。

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题