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