如何将可调用(匿名函数)转换为eval的字符串?
我正在尝试在phpunit中编写单元测试,使用runkit来覆盖方法。特别是,runkit_method_redefine()
需要一个字符串参数eval()
- 稍后调用。
我希望我的测试代码有语法高亮,所以我不想在字符串中编写代码,所以我想做类似的事情
deEval(function(){
return 1;
});
将输出
"return 1;"
如何轻松完成(例如,不执行源文件,查找源代码行,解析等)?
答案 0 :(得分:4)
注意:我不喜欢这个解决方案,我不会向任何人推荐它,但它确实解决了问题中提出的问题。
class CallableStringifier
{
private static $callables = array();
public static function stringify($callable)
{
$id = count(self::$callables);
self::$callables[$id] = $callable;
return 'return ' . __CLASS__ . "::call($id, func_get_args());";
}
public static function call($id, $args)
{
return call_user_func_array(self::$callables[$id], $args);
}
}
这适用于您的特定用例(基本上是create_function()
)。如果你只是eval()
它将不,因为它依赖于在函数上下文中。
示例:
$func = create_function('$arg1', CallableStringifier::stringify(function($arg1) {
return $arg1;
}));
echo $func(1); // outputs 1
答案 1 :(得分:1)
写了一个效率不高的函数..(不考虑参数)
/**
* Converts method code to string by reading source code file
* Function brackets {} syntax needs to start and end separately from function body
*
* @param Callable $callable method to deevaluate
*
* @return string
*/
public function callableToString($callable) {
$refFunc = new ReflectionFunction($callable);
$startLine = $refFunc->getStartLine();
$endLine = $refFunc->getEndLine();
$f = fopen($refFunc->getFileName(), 'r');
$lineNo = 0;
$methodBody = '';
while($line = fgets($f)) {
$lineNo++;
if($lineNo > $startLine) {
$methodBody .= $line;
}
if($lineNo == $endLine - 1) {
break;
}
}
fclose($f);
return $methodBody;
}