Какова альтернатива функции eval?

я использую eval() в моем текущем проекте такой:

if (class_exists($class_name)) //$class_name depends on user input
    eval($class_name.'::MyStaticMethod()');

eval() выполняется тогда и только тогда, когда класс с именем $class_name существует, поэтому это безопасно, но я все еще не думаю, что это лучшее решение.

могу ли я сделать то же самое, что код выше делает без eval()?

5 ответов


Я недавно ответил этот вопрос. Последняя часть мой ответ: отлично отвечает на этот вопрос и гораздо полезнее для будущих читателей, чем ответы, приведенные здесь. Вот почему я отвечаю на свой вопрос.

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'});
      

      демо

    • функция вызова (поддерживается 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_func и call_user_func_array для динамических вызовов функций / методов. Оба прекрасно документированы, поэтому я не буду вдаваться в подробности здесь.
  3. даже если все выше не хватает PHP 5 поставляется с большим Reflection API. К сожалению, в документации мало примеров, но отражение-довольно большая тема для рассмотрения здесь. В принципе, не так уж важно использовать отражение после прочтения того, как оно работает.

Я бы предложил call_user_func.

альтернатива call_user_func() будет называть это так:

$class_and_method = 'Class::MyStaticMethod()';
$class_and_method();

да:

call_user_func(array($class_name, 'MyStaticMethod'));

начиная с PHP 5.3+,

$class_name::MyStaticMethod();

Adisory: userinput + eval = отверстие безопасности;

также eval-дорогостоящая операция, требующая разбора строки в действенном формате(дерево разбора, абстрактное дерево синтаксиса и т. д.) и выполнение новой найденной логики.

вы не хотите использовать eval каждый кусочек кода. Используйте eval, если у вас есть что-то для него, чтобы жевать или, скорее, поместить эту логику где-то, где она многоразова и параметризована, например, функция.

также с php 5.4

$method = array('class_name', 'method_name');
$method(); // calls class_name::method_name()