I'm trying to retrieve an item from a multi-dimensional array through a string that describes the path into the array (like first.second.third
).
I've chosen the approach as shown here (also available on ideone):
<?php
// The path into the array
$GET_VARIABLE = "a.b.c";
// Some example data
$GLOBALS["a"]= array("b"=>array("c"=>"foo"));
// Construct an accessor into the array
$variablePath = explode( ".", $GET_VARIABLE );
$accessor = implode( "' ][ '", $variablePath );
$variable = "\$GLOBALS[ '". $accessor . "' ]";
// Print the value for debugging purposes (this works fine)
echo $GLOBALS["a"]["b"]["c"] . "
";
// Try to evaluate the accessor (this will fail)
echo $$variable;
?>
When I run the script, it will print two lines:
foo
PHP Notice: Undefined variable: $GLOBALS[ 'a' ][ 'b' ][ 'c' ] in ...
So, why does this not evaluate properly?
I think the $$
notation only accepts a variable name (ie. the name of a variable). You are actually trying to read a variable named "$GLOBALS[ 'a' ][ 'b' ][ 'c' ]
", which does not exist.
As an alternative ($GET_VARIABLE
seems to be your input string), you could try this:
$path = explode('.', $GET_VARIABLE);
echo $GLOBALS[$path[0]][$path[1]][path[2]];
Wrap this in a suitable loop to make it more dynamic; it seems to be trivial.
It looks like PHP is treating your entire string like a variable name, and not as an array.
You could try using the following approach instead, as it would also probably be simpler.
<?php
// The path into the array
$GET_VARIABLE = "a.b.c";
// Some example data
$GLOBALS["a"]= array("b"=>array("c"=>"foo"));
// Construct an accessor into the array
$variablePath = explode( ".", $GET_VARIABLE );
//$accessor = implode( "' ][ '", $variablePath );
//$variable = "\$GLOBALS[ '". $accessor . "' ]";
// Print the value for debugging purposes (this works fine)
echo $GLOBALS["a"]["b"]["c"] . "
";
// Try to evaluate the accessor (this will fail)
echo $GLOBALS[$variablePath[0]][$variablePath[1]][$variablePath[2]];
?>
Here's some code I wrote to access $_SESSION variables via dot notation. You should be able to translate it fairly easily.
<?php
$key = "a.b.c";
$key_bits = explode(".", $key);
$cursor = $_SESSION;
foreach ($key_bits as $bit)
{
if (isset($cursor[$bit]))
{
$cursor = $cursor[$bit];
}
else
{
return false;
}
}
return $cursor;
Here's one more solution using a helper function:
function GetValue($path, $scope = false){
$result = !empty($scope) ? $scope : $GLOBALS;
// make notation uniform
$path = preg_replace('/\[([^\]]+)\]/', '.$1', $path); // arrays
$path = str_replace('->', '.', $path); // object properties
foreach (explode('.', $path) as $part){
if (is_array($result) && array_key_exists($part, $result)){
$result = $result[$part];
} else if (is_object($result) && property_exists($result, $part)){
$result = $result->$part;
} else {
return false; // erroneous
}
}
return $result;
}
And example usage:
// Some example data
$GLOBALS["a"] = array(
'b' => array(
'c' => 'foo',
'd' => 'bar',
),
'e' => (object)array(
'f' => 'foo',
'g' => 'bar'
)
);
$bar = array(
'a' => $GLOBALS['a']
);
echo $GLOBALS['a']['b']['c'] . "
"; // original
// $GLOBALS['a']['b']['c']
echo GetValue('a.b.c') . "
"; // traditional usage
// $GLOBALS['a']['b']['c']
echo GetValue('a[b][c]') . "
"; // different notation
// $bar['a']['b']['c']
echo GetValue('a.b.c', $bar) . "
"; // changing root object
// $GLOBALS['a']['e']->f
echo GetValue('a[e]->f') . "
"; // object notation