0
<?php

function compute($input){

        $compute = create_function('', 'return '.$input.';');
        return 0 + $compute();
    
}

$test = array(
    '5 + 5',
    '3 +( 2 * 3)',
    '(3 + 2) * 3',
    '3 + 2 * 3',
    '(3-2-1)*3'
    
);

foreach( $test AS $string){
    echo compute( $string);
    echo "<br />";
}

http://sandbox.onlinephpfunctions.com/code/61ee53b5477d7450ff89f4f012915a44e609000b

上面的代码在 PHP 7.2 中被弃用了。大多数遇到此问题的其他人被告知使用匿名函数。但在这种情况下,我不知道如何使用它。

4

2 回答 2

0

如果您真的想在整个解决方案中继续使用 PHP,那么一个简单的解析器,也许是递归下降,或者像这样的解析器会很好地完成这项工作。您可以很容易地使用这样的系统来评估自定义公式,而无需求助于 eval。

就个人而言,我想要一些可以安全地评估 php 中的整个函数(使用循环、条件等)的东西,所以我使用了一个非常轻量级的 javascript 解释器,称为 duktape,它可以作为模块编译到 php 7 中。然后,您可以调用它来评估 javascript 函数,这些函数本质上很简单,除了能够返回值并从原始脚本中获取输入外,没有输入/输出功能。

我是这样做的:

    /* Execute a javascript function. Requires the duktape extension to be included in PHP.
     * Accepts an array of variables by name to include as parameters to the called code.
     * The code is expected to return a value, which should be scalar (numeric, string or null).
     */
    function jsfunction($inputs, $code)
    {
            $duktape = new Duktape();

            $javascript = "function e() {";
            foreach ($inputs as $name=>$value) {
                    $javascript .= "var " . $name . ' = ' . json_encode((object)$value) . ";\n";
            }
            $javascript .= $code . "}\ne();";

            try {
                    $result = $duktape->eval($javascript);
            }
            catch (Exception $e) {
                    return null;
            }
            return $result;
    }

参数必须作为名称/值对的数组传递,例如传递 ['a'=>42] 使名称为 'a' 的变量对 javascript 可见,值为 42。 $code 包含 javascript 函数体, 周围没有大括号,必须以 return 语句结尾。

希望这可以帮助!

于 2018-07-18T10:49:19.720 回答
0

哇,编写自己的 'eval()' 函数的效率真的很低。但对于在受损系统上获得持久性很有用。也许这就是该功能被弃用的原因?

如果您要解决的问题您的测试用例,那么要么使用 eval (带有经过验证的输入 - /^[^0-9 +-*\/\(\)]$/),要么使用专门为解析此类表达式而设计的库

如果您尝试实现多态代码,那么匿名函数是直截了当的(巧合的是,它实现了多态代码!):

$compute = function () use ($arg) {
      if (preg_match('/^[^0-9 +-*\/\(\)]$/', $arg)) {
           return eval('return '.$arg . ';');
      }
      return false;
  };
于 2018-07-18T10:54:29.153 回答