Конечно, первый совет, который я имею, заключается в том, что вам следует избегать выполнения рекурсивных / повторных вызовов вашей базы данных. Вы должны сделать один вызов, чтобы извлечь все нужные строки в одном наборе результатов и позволить php выполнить сложную часть.
Я решил попробовать нерекурсивный подход. Чтобы разрешить это, набор результатов должен быть подготовлен так, чтобы «более великие» потомки были перечислены первыми. Теперь я понимаю, что вполне возможно, что ваши образцы данных на самом деле не отражают значения вашего проекта, и сортировка не может быть использована для надлежащей подготовки набора результатов - вам придется сообщить мне об этом (и, возможно, обновить свой вопрос, добавив больше точные данные образца).
[см. Встроенные комментарии о том, что происходит в моем сценарии]
* Если вы не используете php7 +, то мой нулевой оператор объединения ($row1['children'] ?? []
) вызовет проблемы.
Вы можете использовать: (isset($row1['children']) ? $row1['children'] : []
Код: ( Демо )
// use ORDER BY belongs_to DESC, id ASC ... or usort() to prepare result set
$resultset = [
['id' => '6a', 'belongs_to' => '5a'],
['id' => '5a', 'belongs_to' => '3a'],
['id' => '8a', 'belongs_to' => '3a'],
['id' => '3a', 'belongs_to' => '1a'],
['id' => '1a', 'belongs_to' => null],
['id' => '2a', 'belongs_to' => null],
['id' => '4a', 'belongs_to' => null],
['id' => '7a', 'belongs_to' => null]
];
foreach ($resultset as $index1 => &$row1) { // make input array modifiable by reference (not working with a copy)
if ($row1['belongs_to']) { // original belongs_to value is not null (not a top-level parent)
foreach ($resultset as $index2 => $row2) { // search for targeted parent
if ($row2['id'] == $row1['belongs_to']) { // parent found
$resultset[$index2]['children'][] = [$row1['id'] => $row1['children'] ?? []]; // store original row as child
unset($resultset[$index1]); // remove original row (no reason to iterate it again in outer loop)
break; // halt inner loop (no reason to iterate further)
}
}
} else { // original belongs_to value is null (top-level parent)
$output[$row1['id']] = $row1['children'] ?? []; // store children to top
}
}
var_export($output);
Выход:
array (
'1a' =>
array (
0 =>
array (
'3a' =>
array (
0 =>
array (
'5a' =>
array (
0 =>
array (
'6a' =>
array (
),
),
),
),
1 =>
array (
'8a' =>
array (
),
),
),
),
),
'2a' =>
array (
),
'4a' =>
array (
),
'7a' =>
array (
),
)