【问题标题】:View a PHP Closure's Source查看 PHP 闭包的源代码
【发布时间】:2014-10-24 12:26:04
【问题描述】:

是否可以反映或以其他方式查看 PHP 闭包对象的来源?也就是说,如果我做这样的事情

$closure = function()
{
    return 'Hi There';
};

然后是这样的

var_dump($closure);

PHP 输出

object(Closure)[14]

也就是说,我知道这个对象是一个闭包,但我不知道它做了什么。

我正在寻找一种允许我转储匿名函数的实际主体的反射方法、函数或调试扩展。

【问题讨论】:

    标签: php closures


    【解决方案1】:

    你能从PHP中得到的东西是有限的,使用反射你只能得到函数的参数签名和源代码文件的起止行。我曾经写过一篇关于这个的博客文章:http://www.metashock.de/2013/05/dump-source-code-of-closure-in-php/ ...

    它使用反射将我引导至以下代码:

    function closure_dump(Closure $c) {
        $str = 'function (';
        $r = new ReflectionFunction($c);
        $params = array();
        foreach($r->getParameters() as $p) {
            $s = '';
            if($p->isArray()) {
                $s .= 'array ';
            } else if($p->getClass()) {
                $s .= $p->getClass()->name . ' ';
            }
            if($p->isPassedByReference()){
                $s .= '&';
            }
            $s .= '$' . $p->name;
            if($p->isOptional()) {
                $s .= ' = ' . var_export($p->getDefaultValue(), TRUE);
            }
            $params []= $s;
        }
        $str .= implode(', ', $params);
        $str .= '){' . PHP_EOL;
        $lines = file($r->getFileName());
        for($l = $r->getStartLine(); $l < $r->getEndLine(); $l++) {
            $str .= $lines[$l];
        }
        return $str;
    }
    

    如果你有以下闭包:

    $f = function (Closure $a, &$b = -1, array $c = array())
      use ($foo) 
    {
        echo $this->name;
        echo 'test';
    };
    

    closure_dump() 将给出以下结果:

    function (Closure $a, &$b = -1, array $c = array (
    )){
     use ($foo)
    {
        echo $this->name;
        echo 'test';
    };
    

    你看到它是不完美的(数组参数)。它也不能正确处理一些边缘情况,特别是如果闭包是嵌套的,或者多个内联闭包将在一行中传递给一个函数。后者对我来说看起来最有问题。因为,您只能从反射中获得开始行和结束行,在这种情况下,这两个函数都将在该行上,并且您没有有用的信息来决定应该转储其中的哪一个。到目前为止,我还没有找到解决方案,也不确定是否有解决方案。

    但是,在大多数情况下,它至少应该有助于调试,只要您不依赖它。 Feel free to enhance it!

    【讨论】:

    • 如何在不使用 eval() 的情况下评估修改后的结果代码?
    • 修改后是什么意思?
    • 我知道这是旧的,但它仍然是我的情况.. 好吧,修改后意味着我已经采用了反射的闭包代码,删除了一些行并添加了其他行,因为它现在只是一个字符串,我需要在不使用 eval() 的情况下评估修改后的代码
    • 你能解释一下用例吗?也许我可以给你一个比使用eval()更好的建议。
    • 当然,这里:github.com/rinvex/extensions/blob/develop/src/… 如您所见,我只是: 1. 反映路线关闭; 2. 加前缀; 3. 并重新评估它(第 729 行)
    猜你喜欢
    • 1970-01-01
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多