Let's say I have the following multi-dimensional array:
$fruits['apple']['name'] = 'macintosh';
Is there any way of referencing the entire key path in a single variable?
I would like to somehow do the following:
$path = "['apple']['name']";
echo $fruits[$path];
//output would be "macintosh"
5 Answers 5
Is there any way of referencing the entire key path in a single variable?
1) In a way like this: $fruits[$variable], the answer is no, there isn't.
Of course, there are several ways you can split a single $variable in two or more, and then use its parts separetely ($fruits[$part1][$part2])
This is a generic solution:
function get_path($array, $path)
{
$value = $array;
$parts = explode("']['", trim($path, "[']"));
foreach($parts as $key)
{
$value = $value[$key];
}
return $value;
}
$fruits['apple']['name'] = 'macintosh';
$path = "['apple']['name']";
echo get_path($fruits, $path);
// output = 'macintosh'
2) As also pointed, you could use "eval", which is not recommended:
$fruits['apple']['name'] = 'macintosh';
$path = "['apple']['name']";
eval('echo $fruits' . $path . ';');
// output = 'macintosh'
3) Finally, if you want to access an element of the array using a reference variable, then simply:
$fruits['apple']['name'] = 'macintosh';
$path &= $fruits['apple']['name'];
echo $path; // output = 'macintosh'
$path = 'MSX';
echo $fruits['apple']['name']; // output = 'MSX'
Comments
There is obviously the horrible, never-to-be-used approach: eval()
But if you really want to do something like this, I would prefer something like this approach:
function &array_value_by_address (&$array, $address, $addressSeparator = '/') {
$parts = explode($addressSeparator, $address);
$thisLevel = array_shift($parts);
if (isset($array[$thisLevel])) {
if ($parts) {
$ref = &array_value_by_address($array[$thisLevel], implode($addressSeparator, $parts));
return $ref;
} else {
return $array[$thisLevel];
}
}
}
Because of the references in the function declaration, it's also possible to catch the return value in a variable and use it to modify the source array. This is optional - if you omit the & prefix at call time the caught value will simply be a copu and not a reference.
The caveat though - the function will return NULL if the "address" within the array does not exist, but there is no way to distinguish between this situation and a NULL value stored within the array.
Comments
J Brun's #3 answer is your best bet, however, his answer is not correct as he has demonstrated the bitwise-AND operator (&=) and not the referential assignment. This is the corrected code:
$fruits['apple'] = array( 'name' => 'macintosh' );
$path = &$fruits['apple']['name'];
echo $path; // outputs 'macintosh';
Comments
References might be what you need:
$path = &$fruits['apple']['name'];
Now every time you would access $path, it's the value of $fruits['apple']['name'] that will be used (or changed, etc.).
1 Comment
What you want to do is not directly possible - it would be ambigous if variables are chained.
You will need to write an accessor function such as
define('SEPARATOR','|');
function getElement($array,$path) {
$path=explode(SEPARATOR,$path);
$out=&$array;
foreach ($path as $step) {
if (!isset($out[$step])) return null;
$out=$out[$step];
}
return $out;
}
$path="apple|name";
echo getElement($fruits,$path);
$fruits['apple/name']to be valid