eval()函数不返回函数结果

3

我有一个存储在数据库列中的方法名称,看起来像这样:

customs::nicknames($data)

这是相关的类:
    class customs extends service {

    function __construct() {
        parent::__construct();
    }

    public static function nicknames($data) {
        return $data;
    }

}

当我以这种方式调用它时:

$merge = eval($error['custom'] . ';');
$data变量的内容没有返回。 只是为了尝试,我尝试使用echo,它正确地返回了将数组转换为字符串的php错误。 因此,变量$data被正确读取。但为什么它不返回任何内容呢?
如果我尝试不使用eval()调用此方法,像这样:
$merge = customs::nicknames($data);

$data 已正确返回。

那么问题出在哪里呢?

为什么 eval() 无法返回方法结果?我该如何解决这个问题?


你尝试过使用 eval('return ' . $error['custom'] . ';'); 吗? - FloydThreepwood
1个回答

22

为什么eval()无法返回方法结果?

因为在你的eval部分中没有返回任何东西。

文档:

eval()会返回NULL,除非在被评估代码中调用return,此时传递给return的值将被返回。


如何解决这个问题?

你可以在eval中赋值变量(例如给定示例中的$merge)。例如:

eval('$merge =' . $error['custom'] . ';');

或者return一个值到eval中。例如:

$merge = eval('return '.$error['custom'].';');

注意:在实际应用中不要使用eval

警告:文档

eval() 语言结构非常危险,因为它允许执行任意 PHP 代码。 因此不建议使用。如果您已经仔细验证过除使用此结构外没有其他选项, 则要特别注意不要在没有适当验证之前将任何用户提供的数据传递给它


如果 eval() 非常危险,那么有没有另一种安全读取字符串作为代码的方法?

是的,有(实际上有多种):

  1. PHP 是一种非常动态的语言。它有能力对字符串进行以下操作:

    • 定义和/或获取变量(支持自 PHP 4.3 起)。例如:

      $variableName = 'MyVariable';
      // Create new variable with the name defined in variable $variableName
      ${$variableName} = 'MyValue';
      //Outputs: string(7) "MyValue"
      var_dump($MyVariable);
      //Outputs: string(7) "MyValue"
      var_dump(${'MyVariable'});
      

      演示

    • 调用函数(自 PHP 4.3 起支持)。例如:

    • // Create function with the name defined in variable $functionName
      function MyFunction($argument) {
          return 'Argument passed is: '.$argument;
      }
      
      $functionName = 'MyFunction';
      
      // Outputs:
      // string(48) "Argument passed is: Calling MyFunction directly."
      var_dump(MyFunction('Calling MyFunction directly.'));
      // Outputs:
      // string(51) "Argument passed is: Calling MyFunction with string."
      var_dump($functionName('Calling MyFunction with string.'));
      

      演示

    • 创建类的实例(自 PHP 5.0 起支持)。例如:

    • class MyClass {
          public function __construct() {
              echo 'Constructing MyClass'."\n";
          }
      }
      
      $className = 'MyClass';
      
      $objFromString = new $className();
      // Outputs: object(MyClass)#1 (0) {}
      var_dump($objFromString);
      

      演示

    • 调用静态方法(PHP 5.0及以上支持)。例如:

    • class MyClass {
          public static function staticMethod() {
              return 'MyClass::staticMethod called';
          }
      }
      
      $staticMethodName = 'staticMethod';
      // Outputs: string(28) "MyClass::staticMethod called"
      var_dump(MyClass::$staticMethodName());
      

      演示

      从 PHP 5.3 开始,类名也可以用字符串来定义。例如:

      class MyClass {
          public static function staticMethod() {
          return 'MyClass::staticMethod called';
          }
      }
      
      $className = 'MyClass';
      $staticMethodName = 'staticMethod';
      
      var_dump($className::$staticMethodName());
      var_dump($className::staticMethod());
      

      演示

    • 调用对象的实例方法(自PHP 5.0起支持)。例如:

    • class MyClass {
          public function instanceMethod() {
              return 'MyClass::instanceMethod called';
          }
      }
      
      $methodName = 'instanceMethod';
      
      $obj = new MyClass();
      // Outputs: string(30) "MyClass::instanceMethod called"
      var_dump($obj->$methodName());
      

      演示

    • 访问对象的静态和实例属性(从 PHP 5.0 开始支持)。例如:

    • class MyClass {
          public static $myStaticProperty;
          public $myInstanceProperty;
      }
      
      $staticPropertyName = 'myStaticProperty';
      $instancePropertyName = 'myInstanceProperty';
      
      MyClass::${$staticPropertyName} = 'my static value';
      $obj = new MyClass();
      $obj->{$instancePropertyName} = 'my instance value';
      
      var_dump(MyClass::${$staticPropertyName});
      var_dump($obj->{$instancePropertyName});
      

      演示

  2. PHP有两个函数: call_user_funccall_user_func_array用于动态调用函数/方法。两者都有很好的文档,因此我不会在这里详细介绍。
  3. 即使上述所有内容都不足够,PHP 5也带有强大的Reflection API。不幸的是,文档中只有少数示例,但反射是一个相当大的主题,难以在此涵盖所有内容。基本上,在了解其工作原理后,使用反射并不困难。

如果eval()函数是危险的,那么有没有其他安全的方法来读取字符串作为代码呢?这是用于私有API系统,所以我不担心。但将来可能会需要它。 - user2426701
@DiegoPucci 我已经更新了我的答案并提供了替代方案。此外,它是否私有并不重要。根据墨菲定律:任何可能出错的事情最终都会出错 - Leri
1
@DiegoPucci 我已经编辑了答案。我认为你会有兴趣重新阅读一遍。 - Leri

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接