Php评估代码raise“;无法重新声明函数“;局部范围错误

Php评估代码raise“;无法重新声明函数“;局部范围错误,php,scope,eval,Php,Scope,Eval,我试图在for循环中多次在eval块中运行一些php代码。 我的目标是使用不同的输入运行提供的代码,以便在夜间生成一些报告 使用eval的意义在于代码是由用户提供的(仅由具有权限权限的超级管理员提供) 在所计算的代码中,可以声明一些函数(对我来说没问题,这样代码看起来更干净) 问题是,当代码第二次运行时(在第二次循环迭代中),它会给我一个错误“cannotredecalefunctionxxx”,我不理解为什么 正如手册所说: 代码将在调用eval()的代码范围内执行 所以在我的例子中,我假设在

我试图在for循环中多次在eval块中运行一些php代码。 我的目标是使用不同的输入运行提供的代码,以便在夜间生成一些报告

使用eval的意义在于代码是由用户提供的(仅由具有权限权限的超级管理员提供)

在所计算的代码中,可以声明一些函数(对我来说没问题,这样代码看起来更干净)

问题是,当代码第二次运行时(在第二次循环迭代中),它会给我一个错误“cannotredecalefunctionxxx”,我不理解为什么

正如手册所说:

代码将在调用eval()的代码范围内执行

所以在我的例子中,我假设在“php_customreport::get_data”局部范围内

对“php_customreport”的引用由“report_custom”类持有,而该类又由for循环中的主代码持有。 因此,当我在for循环的末尾调用“unset”时,我希望所有内容都会被php破坏(因为没有其他引用)

发生了什么事?尽管eval函数是从类中的函数内部调用的,但evaleated代码仍在全局范围内运行? 为什么这些类没有被php破坏,我必须“等待”一段时间让垃圾收集器工作

现在我已经找到了一种解决方法,将函数delcare封装在“function_exist()”函数中的求值代码中,但我并不喜欢它,因为这样我就必须依赖于谁来编写代码,而这些代码是在求值中编写的,我不想这样做

这是我的代码:

主要切入点:

....
foreach ($filterdata as $f => $value) {
  $reportclass = new \report_custom($report);
  $id = $reportclass->create_report(true, [$f]);
  unset($reportclass, $id);
}
...
报表自定义类:

class report_custom extends report_base {
  public function create_report($background = false, $cronFilters = null) {
    ...
    $classname = $config->lang.'_customreport';
    $class = new $classname();
    $dataset = $class->getData($code, $filterData);
    ...
  }
}
Php_customreport类:

class php_customreport implements custombase {

  public function getData(string $code, array $filters = []): string 
      ...
      return json_encode(eval($code));
  }
}
评估代码:

...
report logics..
...
function a_function_to_declare() {
  ...
}
希望我已经提供了所有有用的细节


我知道不鼓励使用“eval”,但在这种情况下,要求运行用户提供的代码。

范围适用于变量,而不是函数。PHP中没有“本地函数”这样的东西。一旦你评估了你的代码,这个函数就会全局存在。将其包装到条件检查
函数_exists
中可能是解决此问题的最快方法。