Древовидные комментарии с бесконечной вложенностью

sanu0074

Новичок
Есть идея написать древовидные комментарии, не знаю на сколько она тупая или хорошая, и как сильно нагрузит сервер, но степень вложенности получится = 2

Есть таблица комментов:

id - id комента
content_id => id поста к которому принадлежат комменты
parent_id => id родительского коммента
..... и другие данные

При добавлении коммента, записываем parent_id = NULL - если это комментарий, не ответ на какой-либо (нет родителя)
или parent_id = id_коммента - которому ответили (родитель)

При извлечении:
- выбираем все комменты с нужным content_id
- проходим циклом по извлеченному массиву, если parent_id = NULL - приступаем к следующей итерации цикла, если в parent_id чтото есть - то извлекаем нужный коммент

Сформированную строку отдаем в браузер.

НУЖНО, переделать эту идею так чтобы степень вложенности была бесконечная.

Для этого необходимо что-то абсолютно новое или как-то можно доработать эту идею?
Интересны ваши предложения. Спасибо за внимание.
 

riff

Новичок
Когда-то давно делал функцию без рекурсии. Одним циклом загружаешь из базы записи, вторым "сопоставляешь".

В php4 нельзя было
foreach ($nodes as $key=>&$node)

и объекты не работали правильно, поэтому приходилось городить "$keys[] = $node['id']; //заполняем список ключей(ID)"
 
Последнее редактирование:

sanu0074

Новичок
это называется списки смежности, можешь рекурсией делать сколько угодно уровней
http://phpclub.ru/faq/Tree/Al?v=4nm
а если в базу при добавлении, записывать к parent_id записывать уровень вложенности (определять с помощью JS), а при извлечении извлечь все и пройтись циклом по данным сформировав массив в виде дерева и потом выводить?
 

hell0w0rd

Продвинутый новичок
sanu0074
А можно вообще хранить вложенный массив в сериализованном виде, вот только зачем? Ради скорости? В рекурсии нет ничего плохого, тем более что эту задачу можно решить без рекурсии - вам написли же выше
 

Фанат

oncle terrible
Команда форума
Наверное, не с бесконечной вложенностью, а просто вложенностью, ограниченной, скажем, 10-ю уровнями
 

sanu0074

Новичок
Сделал, но не работает, косяк где-то:
PHP:
$str = "<ul>";

$pcm=array();

for($i=0;$i<count($comments);$i++){
	 if(!empty($comments[$i]["parent_id"])){
		 $pcm[$comments[$i]["parent_id"]]=$comments[$i];
	 }
}

function buildTree($pid){
	if(isset($pcm[$pid])){
		$tree = '<ul>';
		   $tree .= '<li style="background:green">'.$pcm[$pid]['text'];
		   if(!empty($pcm[$pid]["parent_id"])){$tree.=buildTree($pcm[$pid]["parent_id"]);}
		   $tree .= '</li>';
		$tree .= '</ul>';
	  }
	  else {return NULL;}
	  return $tree;
}

for($i=0;$i<count($comments);$i++){
	$str.="<li style='background:red'>".$comments[$i]["text"]."</li>";
	 if(!empty($comments[$i]["parent_id"])){
		 $str.=buildTree($comments[$i]["parent_id"]);
	 }
}

echo "</ul>".$str;
 

Andkorol

Новичок
Откуда в функции buildTree появилась переменная $pcm ?
PS: весь код несуразный какой-то.
 

sanu0074

Новичок
Вот исправил ошибки:
PHP:
$str = "<ul>";

$pcm=array();

for($i=0;$i<count($comments);$i++){
	 if(!empty($comments[$i]["parent_id"])){
		 $pcm[$comments[$i]["parent_id"]]=$comments[$i];
	 }
}

function buildTree($pid,$pcm){
	if(isset($pcm[$pid])){
		$tree = '<ul>';
		   $tree .= '<li style="background:green">'.$pcm[$pid]['text'];
		   if(!empty($pcm[$pid]["parent_id"]) && $pcm[$pid]["parent_id"]!=$pid){$tree.=buildTree($pcm[$pid]["parent_id"],$pcm);}
		   $tree .= '</li>';
		$tree .= '</ul>';
	  }
	  else {return NULL;}
	  return $tree;
}
for($i=0;$i<count($comments);$i++){
	 if(empty($comments[$i]["parent_id"])) $str.="<li style='background:red'>".$comments[$i]["text"]."</li>";
	 if(!$comments[$i]["parent_id"]){
		 $str.=buildTree($comments[$i]["id"],$pcm);
	 }
}
echo $str."</ul>";
но есть проблема тут, комменты дочерние затирать будут друг друга, то есть одному родителю - один дитя:
PHP:
for($i=0;$i<count($comments);$i++){
	 if(!empty($comments[$i]["parent_id"])){
		 $pcm[$comments[$i]["parent_id"]]=$comments[$i];
	 }
}
Как же обойти эту проблему?
 

riff

Новичок
Это ты мою функцию в это превратил?
for($i=0;$i<count($comments);$i++){
if(!empty($comments[$i]["parent_id"])){
$pcm[$comments[$i]["parent_id"]]=$comments[$i];
}
}
Постирал всё и теперь не работает? А ведь там, как минимум, значки "&" не для красоты были...
 

evgeshonok

Новичок
1)Находишь первый элемент с parentId == null;
2)Записываешь его id во временную переменную, допустим - $currentId, а также сам элемент в массив, который будет отсортирован
($newArray[id]; то есть коммент храним по ключу равному его Id);
3)Удаляешь элемент с основного массива($comments[]);
4)Дальше начинаешь поиск, где parrentId == $currentId. Нашел? Возврат к шагу 2). Нет? Идем дальше.
5)Находишь в отсортированном массиве parrentid родителя и записываешь его в $currentId( $currentId = $newArray[$currentId]['parentId']);
6)Нашел? Возврат к шагу 2). Нет? Возврат к шагу 5).
Ах да, когда основной массив($comments[]) станет пустым не забудь выйти из рекурсии.
 
Сверху