Какова альтернатива функции eval?
я использую eval()
в моем текущем проекте такой:
if (class_exists($class_name)) //$class_name depends on user input
eval($class_name.'::MyStaticMethod()');
eval()
выполняется тогда и только тогда, когда класс с именем $class_name
существует, поэтому это безопасно, но я все еще не думаю, что это лучшее решение.
могу ли я сделать то же самое, что код выше делает без eval()
?
5 ответов
Я недавно ответил этот вопрос. Последняя часть мой ответ: отлично отвечает на этот вопрос и гораздо полезнее для будущих читателей, чем ответы, приведенные здесь. Вот почему я отвечаю на свой вопрос.
PHP имеет функции, которые позволяют избежать использования eval
в большинстве случаев:
-
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});
-
- PHP имеет две функции:
call_user_func
иcall_user_func_array
для динамических вызовов функций / методов. Оба прекрасно документированы, поэтому я не буду вдаваться в подробности здесь. - даже если все выше не хватает PHP 5 поставляется с большим
Reflection
API. К сожалению, в документации мало примеров, но отражение-довольно большая тема для рассмотрения здесь. В принципе, не так уж важно использовать отражение после прочтения того, как оно работает.
Я бы предложил call_user_func
.
альтернатива call_user_func()
будет называть это так:
$class_and_method = 'Class::MyStaticMethod()';
$class_and_method();
Adisory: userinput + eval = отверстие безопасности;
также eval-дорогостоящая операция, требующая разбора строки в действенном формате(дерево разбора, абстрактное дерево синтаксиса и т. д.) и выполнение новой найденной логики.
вы не хотите использовать eval каждый кусочек кода. Используйте eval, если у вас есть что-то для него, чтобы жевать или, скорее, поместить эту логику где-то, где она многоразова и параметризована, например, функция.
также с php 5.4
$method = array('class_name', 'method_name');
$method(); // calls class_name::method_name()