2012-05-20 75 views
6

utilizo eval() en mi proyecto actual así:¿Cuál es la alternativa de la función eval?

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

eval() se ejecuta si y sólo si existe clase con el nombre $class_name por lo que es poco seguro, pero todavía no creo que esta es la mejor solución .

¿Puedo hacer lo mismo lo que hace el código de seguridad sin eval()?

Respuesta

11

he respondido recientemente this question. La última parte del my answer responde perfectamente a esta pregunta y es mucho más útil para los futuros lectores que respuestas proporcionadas aquí. Es por eso que estoy respondiendo mi propia pregunta.

PHP tiene unas características que le da la posibilidad de evitar el uso de eval en la mayoría de los casos:

  1. PHP es un lenguaje muy dinámico. Tiene la capacidad de hacer cosas con strings siguiente:

    • definir y/o obtener la variable (con el apoyo de PHP 4.3). Por ejemplo:

      $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'}); 
      
      función de Llamada

      Demo

    • (soportado desde PHP 4.3). Por ejemplo:

      // 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

    • Crear instancia de la clase (con el apoyo de PHP 5.0).Por ejemplo:

      class MyClass { 
          public function __construct() { 
           echo 'Constructing MyClass'."\n"; 
          } 
      } 
      
      $className = 'MyClass'; 
      
      $objFromString = new $className(); 
      // Outputs: object(MyClass)#1 (0) {} 
      var_dump($objFromString); 
      

      Demo

    • método estático Call (soportado desde PHP 5.0). Por ejemplo:

      class MyClass { 
          public static function staticMethod() { 
           return 'MyClass::staticMethod called'; 
          } 
      } 
      
      $staticMethodName = 'staticMethod'; 
      // Outputs: string(28) "MyClass::staticMethod called" 
      var_dump(MyClass::$staticMethodName()); 
      

      Demo

      Y a partir de PHP 5.3 nombre de clase también puede ser definido por la cadena. Ejemplo:

      class MyClass { 
          public static function staticMethod() { 
          return 'MyClass::staticMethod called'; 
          } 
      } 
      
      $className = 'MyClass'; 
      $staticMethodName = 'staticMethod'; 
      
      var_dump($className::$staticMethodName()); 
      var_dump($className::staticMethod()); 
      

      Demo

    • Call instancia de método de objeto (con el apoyo de PHP 5.0). Por ejemplo: las propiedades estáticas y de instancia

      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

    • de acceso de objeto (con el apoyo de PHP 5.0). Por ejemplo:

      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 tiene dos funciones: call_user_func y call_user_func_array para las llamadas de función/método dinámico. Ambos están perfectamente documentados, así que no entraré en detalles aquí.
  3. Incluso si todo lo anterior no es suficiente PHP 5 viene con gran Reflection API. Lamentablemente, la documentación tiene pocos ejemplos, pero la reflexión es un tema bastante amplio para tratar aquí. Básicamente, no es un gran problema utilizar la reflexión después de leer cómo funciona.
+2

Toda esta información (acceso dinámico a variable/funciones y miembros de instancia/estáticos) es un conocimiento bastante común y parte de los documentos PHP. Agregar todo esto aquí como respuesta no es particularmente útil sin cambiar la pregunta de "qué es la alternativa de eval" a "qué acceso dinámico ofrece PHP". –

6

me gustaría sugerir call_user_func.

Una alternativa a call_user_func() sería llamar así:

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

sí:

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

Adisory: userinput + eval = agujero de seguridad;

También es eval una operación costosa que requiere analizar la cadena en un formato procesable (árbol de análisis sintáctico, árbol de sintaxis abstracta, etc.) y la ejecución de la nueva lógica encontrado.

Usted no quiere a eval cada golosina poco de código. Utilizar eval si tiene algo para que pueda morder o más bien que la lógica puso en algún lugar donde es reutilizable y parametrizada como una función.

También a partir de PHP 5,4

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

'eval' does _not_ crea un nuevo proceso. Prueba: ' scy

+1

De acuerdo, modificado y retractado. –

3

A partir de PHP 5.3+,

$class_name::MyStaticMethod(); 
Cuestiones relacionadas