Вывод комментариев с иерархической структурой

Здравствуйте, как реализовать вывод комментариев как на хабре?
Меня интересует как это будет выглядеть на серверной стороне, в плане вёрстки и стилей для таких комментариев всё понятно.

К примеру у меня есть таблица:

Messages:
id
pid
topic_id
message

Где pid — идентификатор родительского комментария.
  • Вопрос задан
  • 8821 просмотр
Пригласить эксперта
Ответы на вопрос 8
taliban
@taliban
php программист
Серверный вариант:
1. Считываем все из базы
2. Строим дерево
3. Проходим по дереву и выводим каменты
4.!!!
5. PROFIT
Ответ написан
@Lergero
Прочтите статью
www.getinfo.ru/article610.html — все достаточно ясно. Я для себя даже распечатал
Ответ написан
Вообще говоря, есть три подхода.

Первый и самый простой — материализованные пути, это когда мы для каждого комментария храним весь его путь от корня, то есть имеем такую структуру, которая выглядит как-то так:

1.
1.1.
1.2.
1.2.1.
1.3
2.
2.1.

Ну и так далее. Для получения всех комментариев в нужном порядке необходимо просто сделать запрос на получение всех комментариев, только отсортированных в лексикографическом порядке по полю, которое содержит этот путь. Если не учитывать время выполнения запроса, то асимптотически это дело будет работать за O(n), где n — количество комментариев.

Второй подход, чуть посложнее, но выглядящий менее криво — для каждого комментария хранить номер родительского. После того, как мы сделали запрос на получение комментариев, отсортированных по id, мы пробегаем по этим комментариям. Будем строить дерево комментов. Понятно, что если у какого-то комментария есть родитель, то мы его уже добавили в дерево, так как у нас комментарии приходят в отсортированном порядке по их номеру. Поэтому возьмём номер родительского комментария и вставим в список его детей текущий коммент (т. е. что-то типа children[parent_id].insert(node_id)). После такого прохода получим дерево, с которым дальше можем делать что угодно. Получаем асимптотику O(n) при использовании обычных массивов и O(n log n) при использовании ассоциативных массивов, но меньший расход памяти.

Третий подход — использовать уже указанные выше Nested Sets, но на практике, по-моему, их никто не использует.
Ответ написан
TheHorse
@TheHorse
Рекомендую хранить дерево другим образом:
id…… pos
1…… '00'
2…… '01'
3…… '0000'
4…… '0001
Где pos — позиция коммента.
pos = pos(parent(last_child)) + 1 (если parent имеет childs);
pos = pos(parent) + '00'; ( в любом другом случаее).

Строка pos хранит точное положение коммента, по ней можно определить parent и всех child. А самое главное, для вывода дерева, достаточно сделать запрос:
select * from comments order by pos;
и одним циклом вывести весь результат на экран (без доп операций), указывая отступ от левого края равным длине строки pos.
Ответ написан
dudeonthehorse
@dudeonthehorse
Email Developer
Я уже задавал подобный вопрос. Возможно вам ответы будут полезны
Ответ написан
Комментировать
interrupt_controller
@interrupt_controller
функция комментарий(id родителя)
{

}
Ответ написан
mark_ablov
@mark_ablov
можно использовать вспомогательную таблицу родителей.
там всего 3 поля — id, parentId, parentLevel.
собственно, если есть кусок дерева:
-1
--2
---3
то в таблице будет 3 записи:

3, 2, 1
3, 1.
Ответ написан
nixmale
@nixmale
Если еще актуально, то есть и такое решение habrahabr.ru/qa/7550#answer_32413

Отличается оно тем, что добавляя коментарии с помощью ajax не обязательно перестраивать все комменты, а можно перегрузить лишь ветку, начинающуюся с коммента на который отвечаете, и без рекурсиии и строковых полей.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы