2014-08-30 91 views
7

是否可以反映或查看PHP关闭对象的源代码?也就是说,如果我做这样的事情查看PHP关闭的源代码

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

,然后像这样

var_dump($closure); 

PHP输出

object(Closure)[14] 

也就是说,我知道对象是封闭的,但我有不知道它做了什么。

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

回答

10

你可以从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!

+0

如何在不使用eval()的情况下评估修改后的结果代码? – Omranic 2016-02-15 20:15:20

+0

修改后*代表什么意思? – hek2mgl 2016-02-15 20:21:04

+0

我知道这是旧的,但它仍然是我的情况..好吧,修改意味着我已经采取了反射的闭包代码,删除了一些行,并添加了其他人,因为它现在只是一个字符串,我需要评估导致修改的代码不使用eval() – Omranic 2016-02-28 18:15:51