PHP: рекурсивный перебор многомерного массива

У меня есть многомерный массив, который выглядит примерно так:

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 ...

И рекурсивная функция, которая перечисляет все [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;

Это дает мне такой список:

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
...
...
...
...

Но я хочу, чтобы каждая строка имела отступ в зависимости от ее уровня:

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
            ...
        ...
    ...
...

Как я могу это сделать?

Я подумал о включении инкрементных операторов $counter и if. Затем if (!empty($value['children'])) { $counter++; }. Поэтому, если счетчик равен 1, добавьте один отступ в начале каждой строки. Если счетчик равен 2, добавьте два отступа и т. д. Но тогда мне нужно уменьшить $counter-- в конце каждого массива после перебора всех дочерних элементов этого массива. Вот где я логически застрял. Как я могу проверить, является ли массив последним массивом в массиве? if (array is last array)) { $counter--; }

Может ли это решение работать? Или есть лучшее решение, о котором я не думаю?


person AlexanderGR    schedule 25.11.2019    source источник
comment
Было бы полезно, если бы вы предоставили свой массив в формате var_export().   -  person Nigel Ren    schedule 25.11.2019


Ответы (1)


Простым способом было бы передать строку заполнения, когда вы вызываете следующий уровень, добавляя вкладку (или вы можете добавить пробелы, если хотите). Затем просто повторите это перед выводом...

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);

Поскольку ваша функция getTree() ничего не возвращает, не стоит захватывать значение и отображать его.

Как я уже упоминал в своем комментарии, было бы полезно, если бы вы предоставили свой массив в формате var_export(). Это упрощает тестирование, поскольку с вашими текущими демонстрационными данными сложно преобразовать их в фактический массив.

person Nigel Ren    schedule 25.11.2019
comment
Спасибо, Найджел! Это решение простое и прекрасно работает. - person AlexanderGR; 25.11.2019