将字符串转换为函数(可调用)并保持缓存

时间:2014-08-19 02:39:34

标签: php eval

我正在尝试制作一个基准测试脚本,我可以输入简短的代码片段来快速评估我的预期。我认为它类似于jsPerf(但出于安全原因,密码保护)。

主循环应如下所示:

  public function run(&$t, $count) {
    //Run setup function
    if(is_callable($this->setup))
      call_user_func($this->setup);
    //Save inital time
    $t($this->name);
    //THE MAIN LOOP
    for($i=0; $i<$count; $i++) {
        call_user_func($this->fn);
    }
    //Save end time
    $t($this->name."_end");
    //return time difference
    return $t[$this->name."-".$this->name."_end"];
  }

但是,这只适用于静态方法 - 在制作脚本时定义了函数:

//New instance of tester
$b = new Benchmarker();
$b->add(
  //Name
  "touch",
  //closure
  function() {
    touch("file.txt");
  },
  //Code seen in final reports
  "touch()"
);

如您所见,我使用的是call_user_func,而不是eval。除了它本身的邪恶功能这一事实外,我还是出于性能原因而避免使用它。如果我正在测试需要大约10ns才能处理的代码而且 eviluation 大约需要100ns,那么我的结果将是相当随机的。

这就是为什么我正在寻找一种将字符串转换为可调用对象的方法。您可以将其视为一次性评估。

$callable = string_to_callable("function() {echo \"Hello world!\";}");
$b->add(
  //Name
  "echo",
  //callable object
  $callable,
  //Code seen in final reports
  "echo \"...\""
);

这可能吗?

<子>注意:

我可以使用include看到有趣的解决方法:

//Code received from the user
$code = "echo \"Hello world!\";";
//Random name for a new function
$rndname = "fn_".rand(0,100000);  //There are smarter ways to do this of course
//String of the new function
$func = "function $rndname() {{$code}}";
//Define a filename
$f = $rndname.".php";
//Put the code in the file
file_put_contents($f, "<?php\n$func\n?".">");
//Include the new script
include $f;
//Call the function
call_user_func($rndname);
//Delete the file
unlink($f);

我真的希望不需要上面的代码!

1 个答案:

答案 0 :(得分:0)

除了创建新文件外,还有一个封闭技巧:

function string_to_callable($string) {
  return eval("return function() {{$string}};");
}
相关问题