AlexanderGR
AlexanderGR

Reputation: 69

PHP: recursively iterating over multi-dimensional array

I have a multi-dimensional array that looks something like this:

Array ( [text] => Level 0-0 => [children] => 
    Array ( 
    [0] => Array ( [text] => Level 1-0 0 => [children] => 
        Array ( 
        [0] => Array ( [text] => Level 2-0 0 => [children] => 
            Array ( 
            [0] => Array ( [text] => Level 3-0 0 ) 
            [1] => Array ( [text] => Level 3-1 0 ) 
            [2] => Array ( [text] => Level 3-2 0 ) 
            [3] => Array ( [text] => Level 3-3 0 ) 
            [4] => Array ( [text] => Level 3-4 0 ) 
            [5] => Array ( [text] => Level 3-5 0 ) ) ) 
        [1] => Array ( [text] => Level 2-1 0 ) 
        [2] => Array ( [text] => Level 2-2 0 => [children] => 
            Array ( 
            [0] => Array ( [text] => Level 3-0 2 ) ) ) 
        [3] => Array ( [text] => Level 2-3 0 ) 
        [4] => Array ( [text] => Level 2-4 0 ) 
        [5] => Array ( [text] => Level 2-5 0 => [children] => 
            Array ( 
            [0] => Array ( [text] => Level 3-0 5 ) 
            [1] => Array ( [text] => Level 3-1 5 ) 
            [2] => Array ( [text] => Level 3-2 5 ) 
            [3] => Array ( [text] => Level 3-3 5 ) 
            [4] => Array ( [text] => Level 3-4 5 ) 
            [5] => Array ( [text] => Level 3-5 5 ) ) ) 
        [6] => Array ( [text] => Level 2-6 0 ) 
        [7] => Array ( [text] => Level 2-7 0 ) 
        [8] => Array ( [text] => Level 2-8 0 ) 
        [9] => Array ( [text] => Level 2-9 0 => [children] => 
            Array ( 
            [0] => Array ( [text] => Level 3-0 9 ) 
            [1] ...
        [10] ...
    [1] ...
Array ( [text] => Level 0-1 => [children] => 
    Array ( 
    [0] => Array ( [text] => Level 1-0 1 => [children] => 
        Array ( 
        [0] => Array ( [text] => Level 2-0 1 => [children] => 
            Array ( 
            [0] => Array ( [text] => Level 3-0 0 ) 
            [1] ...
        [1] ...
    [1] ...
Array ...

And a recursive function that lists out each [text] => Level x-x x

function getTree(array $array) {
    foreach ($array as $key => $value) {
        echo $value['text']."<br>";
        if (!empty($value['children'])) {
            getTree($value['children']);
        }
    }
}

$array = array (...); //array listed above
$tree = getTree($array);
echo $tree;

This gives me a list like this:

Level 0-0
Level 1-0 0
Level 2-0 0
Level 3-0 0
Level 3-1 0
Level 3-2 0
Level 3-3 0
Level 3-4 0
Level 3-5 0
Level 2-1 0
Level 2-2 0
Level 3-0 2
Level 2-3 0
Level 2-4 0
Level 2-5 0
Level 3-0 5
Level 3-1 5
Level 3-2 5
Level 3-3 5
Level 3-4 5
Level 3-5 5
Level 2-6 0
Level 2-7 0
Level 2-8 0
Level 2-9 0
Level 3-0 9
...
...
...
Level 0-1
Level 1-0 1
Level 2-0 1
Level 3-0 0
...
...
...
...

But what I want is the following where each line is indented based on its level:

Level 0-0
    Level 1-0 0
        Level 2-0 0
            Level 3-0 0
            Level 3-1 0
            Level 3-2 0
            Level 3-3 0
            Level 3-4 0
            Level 3-5 0
        Level 2-1 0
        Level 2-2 0
            Level 3-0 2
        Level 2-3 0
        Level 2-4 0
        Level 2-5 0
            Level 3-0 5
            Level 3-1 5
            Level 3-2 5
            Level 3-3 5
            Level 3-4 5
            Level 3-5 5
        Level 2-6 0
        Level 2-7 0
        Level 2-8 0
        Level 2-9 0
            Level 3-0 9
            ...
        ...
    ...
Level 0-1
    Level 1-0 1
        Level 2-0 1
            Level 3-0 0
            ...
        ...
    ...
...

How can I accomplish this?

I've thought about including an incrementing $counter and if statements. Then if (!empty($value['children'])) { $counter++; }. So if counter is 1, add one indent at the beginning of each line. If counter is 2, add two indents, etc. But then I need to decrement $counter-- at the end of every array after iterating over all the children of that array. That's where I'm logically stuck. How can I check if an array is the last array in an array? if (array is last array)) { $counter--; }

Can this solution work? Or is there a better solution I'm not thinking of?

Upvotes: 0

Views: 40

Answers (1)

Nigel Ren
Nigel Ren

Reputation: 57121

A simple way would be to pass in a padding string, when you call the next level add a tab(or you could add spaces if you wish). Then just echo it before your output...

function getTree(array $array, string $pad = '' ) {
    foreach ($array as $key => $value) {
        echo $pad.$value['text']."<br>";
        if (!empty($value['children'])) {
            getTree($value['children'], $pad."\t");
        }
    }
}

getTree($array);

As your getTree() function doesn't return anything, it's not worth capturing the value and displaying it.

As I mentioned in my comment, it would help if you gave your array in var_export() format. That allows easier testing as with your current sample data it's a pain to convert it to an actual array.

Upvotes: 1

Related Questions