2

Suppose you have this array:

$object = array ('a' => array ( 'b' => array('c' = 'value'), 'd' => 3));
$indices = array ('a', 'b', 'c');

Is there an easy way to access $object['a']['b']['c'] (keys from $indices array)?

This is what I tried:

function accessObjectKey ($object, $levels) {
    if (is_string($levels)) 
        $levels = explode ('.', $levels);
    //
    for ($i=0; $i<count($levels); $i++) {
        if ($i == count($levels) && key_exists($levels[$i], $object)) {
            $value = $object[$levels[$i]];
        }
        else {
            $value = accessObjectKey ($object, array_shift($levels));
        }
    }
    return $value;
}

Thank you

Alexandru R
  • 8,560
  • 16
  • 64
  • 98

3 Answers3

2

First of all (you have typo array('c' = 'value'), should be array('c' => 'value'),) I tried to use your code:

$object = array ('a' => array ( 'b' => array('c' => 'value'), 'd' => 3));
$indices = array ('a', 'b', 'c');

echo accessObjectKey($object,$indices);

that returned me an error:

Fatal error: Maximum function nesting level of '100' reached, aborting!

I was little bit confusing by your function code, so sorry I created mine It is not perfect but return value as expected:

function getByPath($arr,$path) {
     if (!isset($arr[$path[0]])) {
        return 'There is no '.$path[0].' element!';
     } elseif(count($path)==1) {
        return $arr[$path[0]];
     } elseif(!is_array($arr[$path[0]])) {
        return 'Element '.$path[0].' is not array! ';
     } else {
    $key = array_shift($path);     
        return getByPath($arr[$key],$path);
     }
}

$object = array ('a' => array ( 'b' => array('c' => 'value'), 'd' => 3));
$indices = array ('a', 'b', 'c');

echo getByPath($object,$indices);

output:

value

Alex
  • 16,739
  • 1
  • 28
  • 51
1

Here's another option, from https://baohx2000.medium.com/reaching-deep-into-arrays-using-array-reduce-in-php-9ff9e39a9ca8

function getArrayPath(array $path, array $deepArray) {
   $reduce = function(array $xs, $x) {
      return (
        array_key_exists($x, $xs)
      ) ? $xs[$x] : null;
   };
   return array_reduce($path, $reduce, $deepArray);
}

$x = [
  'a' => 1,
  'b' => [
    'c' => 2,
    'd' => [3, 4, 5],
  ],
];

print_r(getArrayPath(['b','d', 0], $x));  // 3
Rafael Vega
  • 4,575
  • 4
  • 32
  • 50
0

Another technique is to use explicit stacking.

I came upon this page while searching for related techniques for this CodeReview question.

By "stacking", I actually mean iterate the array of keys which dictate the path to the desired array value and each time a key is found, overwrite the parent array with the newly encountered subarray.

Code: (Demo)

function getFromKeyPath(array $array, array $keys) {
    foreach ($keys as $index => $key) {
        if (!key_exists($key, $array)) {
            throw new Exception("key $key not found at level index $index");
        }
        $array = $array[$key];
    }
    return $array;
}

$array = ['a' => ['b' => ['c' => 'value'], 'd' => 3]];
$keys = ['a', 'b', 'c'];

try {
    var_export(getFromKeyPath($array, $keys));
} catch (Exception $e) {
    echo $e->getMessage();
}
// 'value'
mickmackusa
  • 43,625
  • 12
  • 83
  • 136