Drupal code is heavily array-based, and it utilizes array structures that can be many levels deep. Here are a couple of complementary functions to query and manipulate such arrays:
<?php
/**
* Search for a key in an array, returning a path to the entry.
*
* @param $needle
* A key to look for.
* @param $haystack
* A keyed array.
* @param $forbidden
* A list of keys to ignore.
* @param $path
* The intermediate path. Internal use only.
* @return
* The path to the parent of the first occurrence of the key, represented as an array where entries are consecutive keys.
*/
function array_key_path($needle, $haystack, $forbidden = array(), $path = array()) {
foreach ($haystack as $key => $val) {
if (in_array($key, $forbidden)) {
continue;
}
if (is_array($val) && is_array($sub = array_key_path($needle, $val, $forbidden, array_merge($path, (array)$key)))) {
return $sub;
}
elseif ($key === $needle) {
return array_merge($path, (array)$key);
}
}
return FALSE;
}
/**
* Given a path, return a reference to the array entry.
*
* @param $array
* A keyed array.
* @param $path
* An array path, represented as an array where entries are consecutive keys.
* @return
* A reference to the entry that corresponds to the given path.
*/
function &array_path(&$array, $path) {
$offset =& $array;
if ($path) foreach ($path as $index) {
$offset =& $offset[$index];
}
return $offset;
}
?>
These functions are useful when the key you're looking for is not necessarily located in the array's root level. For example, a form field might be located a few levels deep due to fieldgroups. In that case, you would write something like:
<?php
// Given a $form, find an element and manipulate it.
$path = array_key_path('field_video', $form, array('#field_info'));
if ($path !== FALSE) {
$field_video =& array_path($form, $path);
$field_video['#disabled'] = TRUE;
}
?>
Happy coding!
Comments
Awesome! Thanks:) Saved me a bit of time writing it ;)
An item usually contains both objects and arrays, so I don't think this code will work all the time. And always be careful when using these functions since it can make for a performance hit, and lazy coding.
Better to give a better example instead of directionless comment. You can post an example which works on objects and arrays and help the community more.
I used this lazy coding today and saved lot of headache.
Thanks for the caveat. It's true that no code will work all the time - use with caution!