【问题标题】:eval() does not return the function resultseval() 不返回函数结果
【发布时间】:2014-02-13 16:53:56
【问题描述】:

我有一个存储在 DB 列中的方法名称,如下所示:

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'] . ';'); ?

标签: php eval


【解决方案1】:

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

仅仅是因为您在 eval 部分中没有返回任何内容。

Docs:

eval() 返回 NULL 除非在评估代码中调用 return,在这种情况下返回传递给 return 的值。


我该如何解决这个问题?

您可以在eval 中分配变量(在给定示例中为$merge)。例如:

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

return 中的eval 值。例如:

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

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

Warning from docs:

eval() 语言结构非常危险,因为它允许执行任意 PHP 代码。 它的用途是 气馁。如果您已仔细验证没有其他 选项而不是使用此构造,请特别注意不要通过 任何用户在未正确验证的情况下向其中提供了数据 提前。


如果 eval() 很危险,还有其他方法可以安全地将字符串作为代码读取吗?

是的,有(实际上是):

  1. PHP 是一种非常动态的语言。它有能力用strings做以下事情:

    • 定义和/或获取变量(从 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'});
      

      Demo

    • 调用函数(从 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.'));
      

      Demo

    • 创建类的实例(从 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);
      

      Demo

    • 调用静态方法(从 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());
      

      Demo

      并且从 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());
      

      Demo

    • 调用对象的实例方法(从 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());
      

      Demo

    • 访问对象的静态和实例属性(从 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});
      

      Demo

  2. PHP 有两个函数:call_user_funccall_user_func_array 用于动态函数/方法调用。两者都有完整的文档,所以我不会在这里详细介绍。
  3. 即使上面的一切还不够,PHP 5 也提供了很棒的Reflection API。不幸的是,文档中的示例很少,但反射是这里要讨论的一个很大的话题。基本上,在阅读了反射的工作原理后,使用反射并不是什么大不了的事。

【讨论】:

  • 如果 eval() 很危险,是否有另一种方法可以安全地将字符串作为代码读取?这是针对私有 API 系统的,所以我不担心。但将来我可能需要它
  • @DiegoPucci 我已经用替代方案更新了我的答案。此外,它是否是私人的也没关系。根据墨菲的说法:Anything that can go wrong, will go wrong.
  • @DiegoPucci 我已经编辑了答案。我想你有兴趣重读一本。
猜你喜欢
  • 1970-01-01
  • 2011-12-27
  • 2012-12-27
  • 2020-07-04
  • 1970-01-01
  • 2019-08-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多