2012-05-05 6 views
6

Solo me pregunta si hay una forma de evitar esto (o si es posible).Variables de variable de PHP con la tecla de matriz

Así que tengo una sección de código similar a esta. Tengo una cadena, con un valor que contiene corchetes, similar a los utilizados al acceder a una clave de matriz. Quiero crear esa clave de matriz utilizando el valor de cadenas. Espero que este código tenga un poco más de sentido de lo que quiero decir.

// String that has a value similar to an array key 
$string = 'welcome["hello"]'; 
$$string = 'thisworks'; 

// I could then print the array keys value like this 
print($welcome["hello"]); 

// This would hopefully output 'thisworks'. 

Parece que no funciona correctamente. ¿Es posible (o de qué otra manera puedo hacerlo)?

+2

usa una matriz desde el principio, entonces no tienes estos problemas. – hakre

+0

¿Está intentando analizar JSON, quizás? Describa de dónde provienen estos datos un poco más, si pudiera. –

+0

No se usa JSON.Esta es una versión muy simplificada de lo que realmente está sucediendo, pero en esencia las matrices multidimensionales se usan para construir una nueva serie de opciones. Actualmente estoy usando regexp para detectar si la cadena contiene corchetes, y si lo hace, una instrucción if hace un montón de cosas para crear una matriz. Como puede adivinar, intentar hacer que el método anterior funcione ahorrará todo si se comprueba, y funcionaría para ambas opciones que no contienen corchetes y para los que sí lo hacen. –

Respuesta

3

El siguiente es un ejemplo siguiendo la sintaxis nombre de la variable que se resuelve miembros de la matriz, así:

// String that has a value similar to an array key 
$string = 'welcome["hello"]'; 

// initialize variable function (here on global variables store) 
$vars = $varFunc($GLOBALS); 

// alias variable specified by $string 
$var = &$vars($string); 

// set the variable 
$var = 'World'; 

// show the variable 
var_dump($welcome["hello"]); # string(5) "World" 

Con la siguiente implementación:

/** 
* @return closure 
*/ 
$varFunc = function (array &$store) { 
    return function &($name) use (&$store) 
    { 
     $keys = preg_split('~("])?(\\["|$)~', $name, -1, PREG_SPLIT_NO_EMPTY); 
     $var = &$store; 
     foreach($keys as $key) 
     { 
      if (!is_array($var) || !array_key_exists($key, $var)) { 
       $var[$key] = NULL; 
      } 
      $var = &$var[$key]; 
     } 
     return $var; 
    }; 
}; 

Como no puede sobrecargar las variables en PHP, está limitado al expreso iveness de PHP aquí, es decir, no existe un contexto de escritura para las referencias a variables como valores de retorno de función, lo que requiere el aliasing adicional:

$var = &$vars($string); 

Si algo como esto no satisface sus necesidades, tienes que parchear PHP y si no se una opción, PHP no ofrece las funciones de idioma que está buscando.

Ver también la pregunta relacionada: use strings to access (potentially large) multidimensional arrays.

+0

Gracias de nuevo @hakre. Realmente lo aprecio. –

+0

Fuera de interés, ¿hay alguna manera similar de hacer esto sin el uso de funciones anónimas? Solo por compatibilidad con compatibilidad con versiones anteriores. Lo siento si es una pregunta estúpida, este tipo de PHP es nuevo para mí (funciones anónimas, usando '&' antes de las variables, el uso de 'uso'). –

+0

¿Compatible con versiones anteriores a la versión de PHP? Y claro que sí, puedes simular cualquier cierre con una clase. – hakre

0

Puede usar eval, aunque realmente no lo recomendaría en un entorno de producción, tiene sus ventajas.

<? 
$string = 'welcome["hello"]'; 
eval('$' . $string . " = 'thisworks';"); 

// This also works : eval("$$string = 'thisworks';"); 

// I could then print the array keys value like this 
print($welcome["hello"]); // Prints 'thisworks' 
+1

pero no olvides una cosa. Eval es MALVADO. – marvin

+0

Muy de acuerdo, es tan increíblemente susceptible a que alguien piratee el contenido dentro de la evaluación, especialmente si es dinámico, y ejecuta cualquier comando que desee en su secuencia de comandos. – Bryan

+0

Es una lástima, porque esta parece ser la solución perfecta (eso no implica agregar funciones adicionales). ¿Puedo hacerlo más seguro usando 'call_user_func'? –

1

No, no puedes hacer eso de esa manera. Como alternativa, se puede establecer la variable de referencia usando

$welcomeHello = &$welcome["hello"] 

y luego usar

$welcomeHello = 'thisworks' 

para establecer el contenido material.

Esta sería una forma más correcta e incluso más rápida para configurar elementos de la matriz.

+0

Esta es la mejor manera –

5

En Variable variables caracteres en una cadena tratada literalmente. No interpretan lo que está dentro de la cadena. Por lo tanto, [] caracteres en $string no se tratan como notación de matriz. Más bien se trata como una parte del nombre de la variable.

después de ejecutar $$string = 'thisworks'; PHP crea una variable con el nombre welcome["hello"] literalmente con el valor establecido en thisworks.

Para imprimirlo utilizar esta notación,

print (${'welcome["hello"]'}); 
+0

Posiblemente una pregunta estúpida, pero supongo que no hay forma de decirle a PHP que deje de tomarla literalmente. –

+0

@MatthewRuddy Definitivamente no. ¿Por qué lo necesitas tanto? – RReverser

+0

Es solo una idea que he tratado de poner en práctica. Ya tengo una alternativa de trabajo, pero un método similar a mi publicación original reduciría muchas líneas y sería un poco más eficiente. Siempre me gusta experimentar con formas de hacer las cosas mejor. –

Cuestiones relacionadas