2012-05-20 8 views
6

Я использую eval() в моем текущем проекте, как это:Что такое функция eval?

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

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

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

ответ

11

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

PHP имеет функции, что дает возможность избежать использования eval в большинстве случаев:

  1. PHP является очень динамичным языком. Он имеет возможность делать следующие вещи с strings:

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

Вся эта информация (динамический доступ к переменной/функциям и экземплярам/статическим членам) является довольно распространенным знанием и частью документов PHP. Агрегация всего этого здесь в качестве ответа не особенно полезна, не меняя самого вопроса из «какой альтернативы eval» на «какой динамический доступ предлагает PHP». –

6

Я предлагаю call_user_func.

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

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

да:

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

Adisory: UserInput + Eval = дыра в безопасности;

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

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

Кроме того, как РНР 5,4

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

'eval' does _not_ создает новый процесс. Доказательство: ' scy

+1

Согласовано, изменено и отложено. –

Смежные вопросы