Variables variables que señalan a arrays o anidados objetos
-
19-09-2019 - |
Pregunta
¿Es posible crear una variable apuntando variable en una matriz o de objetos anidados? Los documentos php dicen específicamente que no se puede apuntar a Superglobals pero su claro (al menos para mí) si esto se aplica a las matrices en general.
Aquí está mi intento en la matriz var var.
// Array Example
$arrayTest = array('value0', 'value1');
${arrayVarTest} = 'arrayTest[1]';
// This returns the correct 'value1'
echo $arrayTest[1];
// This returns null
echo ${$arrayVarTest};
Aquí hay un código simple de mostrar lo que quiero decir con objeto var var.
${OBJVarVar} = 'classObj->obj';
// This should return the values of $classObj->obj but it will return null
var_dump(${$OBJVarVar});
Me estoy perdiendo algo obvio aquí?
Solución
Array enfoque elemento :
- nombre del extracto de matriz a partir de la cadena y almacenarlo en
$arrayName
. - índice de extracto de matriz a partir de la cadena y almacenarlo en
$arrayIndex
. - procesarlas correctamente en lugar de en su conjunto.
El código:
$arrayTest = array('value0', 'value1');
$variableArrayElement = 'arrayTest[1]';
$arrayName = substr($variableArrayElement,0,strpos($variableArrayElement,'['));
$arrayIndex = preg_replace('/[^\d\s]/', '',$variableArrayElement);
// This returns the correct 'value1'
echo ${$arrayName}[$arrayIndex];
Propiedades del objeto acercan :
- Explotar la cadena que contiene la clase y la propiedad que desea acceder por su delimitador. (->)
- Asignar esas dos variables a
$class
y$property
. - Analizar por separado en lugar de en su conjunto sobre
var_dump()
El código:
$variableObjectProperty = "classObj->obj";
list($class,$property) = explode("->",$variableObjectProperty);
// This now return the values of $classObj->obj
var_dump(${$class}->{$property});
Funciona!
Otros consejos
Uso = &
asignar por referencia:
$arrayTest = array('value0', 'value1');
$arrayVarTest = &$arrayTest[1];
$arrayTest[1] = 'newvalue1'; // to test if it's really passed by reference
print $arrayVarTest;
En echo $arrayTest[1];
el nombre vars se $arrayTest
con un índice de matriz de 1
, y no $arrayTest[1]
. Los soportes son PHP "palabras clave". Lo mismo pasa con la notación método y el operador ->
. Por lo que tendrá que separarse.
// bla[1]
$arr = 'bla';
$idx = 1;
echo $arr[$idx];
// foo->bar
$obj = 'foo';
$method = 'bar';
echo $obj->$method;
Lo que se quiere hacer suena más como la evaluación de código PHP (eval()
). Pero recuerde: eval es malo. ; -)
Nop no se puede hacer eso. Sólo se puede hacer eso con los nombres de variables, objetos y funciones.
Ejemplo:
$objvar = 'classObj';
var_dump(${$OBJVarVar}->var);
Alternativas puede ser a través eval () o por hacer pre-procesamiento.
$arrayTest = array('value0', 'value1');
$arrayVarTest = 'arrayTest[1]';
echo eval('return $'.$arrayVarTest.';');
eval('echo $'.$arrayVarTest.';');
Esto es, si estás muy seguro de lo que va a ser la entrada.
Por pre-procesamiento:
function varvar($str){
if(strpos($str,'->') !== false){
$parts = explode('->',$str);
global ${$parts[0]};
return $parts[0]->$parts[1];
}elseif(strpos($str,'[') !== false && strpos($str,']') !== false){
$parts = explode('[',$str);
global ${$parts[0]};
$parts[1] = substr($parts[1],0,strlen($parts[1])-1);
return ${$parts[0]}[$parts[1]];
}else{
return false;
}
}
$arrayTest = array('value0', 'value1');
$test = 'arrayTest[1]';
echo varvar($test);