uncovery uncovery - 2 months ago 8x
PHP Question

Creating a dynamic hierarchical array in PHP

I have this general data structure:

$levels = array('country', 'state', 'city', 'location');

I have data that looks like this:

$locations = array(
1 => array('country'=>'USA', 'state'=>'New York', 'city'=>'NYC', 'location'=>'Central Park', 'count'=>123),
2 => array('country'=>'Germany', ... )

I want to create hierarchical arrays such as

$hierarchy = array(
'USA' => array(
'New York' => array(
'NYC' => array(
'Central Park' => 123,
'Germany' => array(...),

Generally I would just create it like this:

$final = array();
foreach ($locations as $L) {
$final[$L['country']][$L['state']][$L['city']][$L['location']] = $L['count'];

However, it turns out that the initial array $levels is dynamic and can change in values and length So I cannot hard-code the levels into that last line, and I do not know how many elements there are. So the $levels array might look like this:

$levels = array('country', 'state');


$levels = array('country', 'state', 'location');

The values will always exist in the data to be processed, but there might be more elements in the processed data than in the levels array. I want the final array to only contain the values that are in the $levels array, no matter what additional values are in the original data.

How can I use the array $levels as a guidance to dynamically create the $final array?

I thought I could just build the string
with implode() and then run eval() on it, but is there are a better way?


Here's my implementation. You can try it out here:

$locations = array(
  1 => array('country'=>'USA', 'state'=>'New York', 'city'=>'NYC', 'location'=>'Central Park', 'count'=>123),
  2 => array('country'=>'Germany', 'state'=>'Blah', 'city'=>'NY', 'location'=>'Testing', 'count'=>54),

$hierarchy = array();

$levels = array_reverse(
    array('country', 'state', 'city', 'location')

$lastLevel = 'count';

foreach ( $locations as $L )
    $array = $L[$lastLevel];

    foreach ( $levels as $level )
        $array = array($L[$level] => $array);

    $hierarchy = array_merge_recursive($hierarchy, $array);