Как многомерный массив из древовидного комментария преобразовать в двумерный массив с одним родительским комментарием
Допустим есть такой массив из комментариев с id и parent_id как ключ к его родительскому комментарию.
$comments = array(
array('id' => 1, 'text' => 'Комментарий 1', 'parent_id' => null),
array('id' => 2, 'text' => 'Комментарий 2', 'parent_id' => null),
array('id' => 3, 'text' => 'Комментарий 3', 'parent_id' => 1),
array('id' => 4, 'text' => 'Комментарий 4', 'parent_id' => 1),
array('id' => 5, 'text' => 'Комментарий 5', 'parent_id' => 2),
array('id' => 6, 'text' => 'Комментарий 6', 'parent_id' => 2),
array('id' => 7, 'text' => 'Комментарий 7', 'parent_id' => 4),
array('id' => 8, 'text' => 'Комментарий 8', 'parent_id' => 4),
array('id' => 9, 'text' => 'Комментарий 9', 'parent_id' => 5),
array('id' => 10, 'text' => 'Комментарий 10', 'parent_id' => 7),
);
И хочу чтобы например "Комментарий 9" был под Комментарием 2 потому что выше уже нету, а Комментария 10 самый родительский был Комментарий 1.
Вот так сперва делал древовидную структуру, а потом преобразовал в двумерный с одним родителем. Всё почти работает, но не показывает сами родительские комментарии.
function buildCommentTree($comments, $parent_id = 0, $depth = 0) {
$comment_tree = array();
foreach ($comments as $comment) {
if ($comment['parent_id'] == $parent_id) {
$comment['depth'] = $depth;
$comment['children'] = buildCommentTree($comments, $comment['id'], $depth + 1);
$comment_tree[] = $comment;
}
}
return $comment_tree;
}
$comment_tree = buildCommentTree($comments);
$resArray = [];
function convertToSimpleArray($array){
global $resArray;
if(!empty($array['children'])){
foreach($array['children'] as $below){
$res = convertToSimpleArray($below);
$below['children'] = [];
$resArray[] = $below;
}
}else{
$resArray[] = $array;
}
return $resArray;
}
foreach ($comment_tree as $comm_tree) {
$arrr[] = array_unique(convertToSimpleArray($comm_tree), SORT_REGULAR);
$resArray = [];
}
Ответы (1 шт):
Поскольку ваш код несколько громоздкий, приведу более простой пример. сделайте сначала два подготовительных шага. Первое - проиндексируйте массив по id.
$data = array_column($comments, null, 'id');
Теперь создайте функцию, которая пройдется вверх по массиву и вернет максимальный родительский id для элемента:
$getTopParent = function($id) use ($data) {
while($parentId = $data[$id]['parent_id']) $id = $parentId;
return $id;
};
С ее помощью теперь обработайте исходный массив, заменив родительские id где надо, а где не надо, добавим replies для ответов:
foreach ($data as $id => &$comment) {
if (!$comment['parent_id']) {
$comment['replies'] = [];
} else {
$comment['parent_id'] = $getTopParent($id);
}
}
Вторым циклом перенесите ответы в ветки:
foreach ($data as $id => $item) {
if ($pid = $item['parent_id']) {
$data[$pid]['replies'][$id] = $item;
unset($data[$id]);
}
}
в целом, можно объединить в рамках одного цикла:
foreach ($data as $id => &$comment) {
if ($comment['parent_id']) {
$comment['parent_id'] = $pid = $getTopParent($id);
$data[$pid]['replies'][$id] = $comment;
unset($data[$id]);
}
}

