Комментарии с уровнем вложения.Как лучше реализовать?

12
AK
На сайте с 04.02.2007
Offline
21
1016

Хочу сделать комментарии. Причём с уровнем вложенности и древовидной структурой (т.е. чтобы для комментариев, которые являются ответом на какой-то другой - был отступ)

Ну что-то вроде этого:

Но никак не соображу как это лучше реализовать.

У меня есть 3 версии:

1) У каждого комментария есть свой id, id комментария к которому он идёт ответом (toComment).

При этом из БД выбираются все комментарии для этой записи с order by `toComment`,`id`

Но как тогда определить отступ и древовидность комментариев? Несколько раз пробегать по массиву? или запоминать какой комментарий на какой идёт ответом?

И представим например что комментарии идут так:

комментарий 1         (id=5 toComment=null)

комментарий 3 (id=12 toComment=5)
комментарий 6 (id=17 toComment=12)
комментарий 8 (id=25 toComment=17)
комментарий 7 (id=20 toComment=12)
комментарий 4 (id=13 toComment=5)
комментарий 2 (id=7 toComment=null)
комментарий 5 (id=16 toComment=7)

То скрипт, а именно sql запрос, будет работать неверно. Т.к. 8 комментарий будет выводится только уже после 7, а должен до него.

Но тут можно ввести ещё одно поле - уровень вложенности или что-то подобное. Да, в прицнипе можно. Но для всего этого тредуются опять же рассчёты. И кажется мне что это всё слишком сложно получается, можно проще.

2) Выбирать сначала комментарии с toComment=null и сортировкой по id.

А затем при выводе данного коментария лезть в БД и смотреть, если ли там запись с toComment равным id этого коммента. Итак до тех пор, пока не будет пройдена вся структура. И легко вычислять отступы тут будет

В целом можно, но а что есть комментариев будет много, и/или много человек будут просматривать эту страницу? Не будет ли серверу плохо от такого кол-ва запросов к БД?

3) Хранить в в toComment всю цепочку. Т.е. так:

комментарий 1         (id=5 toComment=null)

комментарий 3 (id=12 toComment=5.1)
комментарий 6 (id=17 toComment=5.2)
комментарий 8 (id=25 toComment=5.2.1)
комментарий 7 (id=20 toComment=5.3)
комментарий 4 (id=13 toComment=5.4)
комментарий 2 (id=7 toComment=null)
комментарий 5 (id=16 toComment=7.1)

Но считывать всё просто в массив. А затем уже парсить toComment, сортировать массив и выводить на экран.

Но опять же не нравится мне тут считывание этого дела в память и хранение там.

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

Может кто-то сталкивался и знает как лучше это сделать?

Qinghua
На сайте с 01.09.2009
Offline
103
#1

варинат1 + ячейка для вложенности.

где вы тут сложность видите?

Можно и через манипуляции с массивами, но это слишком усложнит код. Лучше немного усложнить данные.

K
На сайте с 31.08.2006
Offline
47
#2

Вам поможет Nested Sets (Вложенные множества). В сети полно информации по этой теме.

Вообще, погуглите что-то типа "Хранение древовидных структур в БД".

Есть даже готовые ПХП-классы для работы с такими таблицами.

Если ничего не найдете отпишитесь мне, попробую помочь.

Размещаем статьи - Украинское СМИ, ПР5, ТИЦ 3000, ЯК, ДМОЗ, домену > 10 лет (/ru/forum/416715)
AK
На сайте с 04.02.2007
Offline
21
#3

Qinghua,

варинат1 + ячейка для вложенности.
где вы тут сложность видите?

Ну по сути это ничего не изменит:

комментарий 1         (id=5  toComment=null level 0)

комментарий 3 (id=12 toComment=5 level 1)
комментарий 6 (id=17 toComment=12 level 2)
комментарий 8 (id=25 toComment=17 level 3)
комментарий 7 (id=20 toComment=12 level 2)
комментарий 4 (id=13 toComment=5 level 1)
комментарий 2 (id=7 toComment=null level 0)
комментарий 5 (id=16 toComment=7 level 1)

И опять же, как тогда сделать order by, чтобы выводить это дерево в нужном порядке?

Собственно тогда тоже придётся считывать в массив и соритровать его.

Или я не правильно вас понял?

Kirilll,

Спасибо. Пока не разбрался как это всё работает,но судя по всему лучше будет взять готовый класс для работы с подобным деревом и немного изменить его под себя.

K
На сайте с 31.08.2006
Offline
47
#4

NestedSets - это не класс. Это принцип хранения древовидных данных.

Там все завязано на том, что каждая запись, кроме ID имеет еще 2 поля - левій и правый ключ. И с помощью этих ключей можно манипулировать с деревом как угодно: перемещать узлы и ветви, удалять ветви без потери целостности дерева, выбирать все дочерние узлы...

Это именно то, что нужно вам. Я в этом уверен.

Поэтому потратьте пару часов на то, чтобы разобраться с этим, и будет вам счастье! )))

Cheltap
На сайте с 27.11.2008
Offline
30
#5

Сортировка.

Одним SQL-запросом это не сделать, Order By тут не поможет в полной мере,

сортировать всё же придётся на уровне скриптов, а не SQL-сервера.

Дизайн.

Первое, что пришло в голову - отдельный DIV для каждого комментария.

В верхней его части выводите текст, а затем размещайте всё его дочернее

хозяйство тем же макаром (каждый комментарий - это DIV)...

[Удален]
#6

я МОГУ ПИСАТЬ!! УРА ЛЮДИ!!!

K
На сайте с 31.08.2006
Offline
47
#7
Cheltap:
Сортировка.
Одним SQL-запросом это не сделать, Order By тут не поможет в полной мере,
сортировать всё же придётся на уровне скриптов, а не SQL-сервера.

При Нестед Сетс делается одним запросом. Сортируется по левому ключу.

Скриптом сортировать - накладно по производительности.

Cheltap:
Дизайн.
Первое, что пришло в голову - отдельный DIV для каждого комментария.
В верхней его части выводите текст, а затем размещайте всё его дочернее
хозяйство тем же макаром (каждый комментарий - это DIV)...

Вложенные ДИВы тоже хорошо.

Но списками (UL - LI), ИМХО, более правильно с точки зрения оптимизации. Ну а CSS-ом можно оформить как угодно, хоть ДИВ, хоть список...

[Удален]
#8

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

а отодвигать как всегда, padding: 0px 30px * $level ;)

Qinghua
На сайте с 01.09.2009
Offline
103
#9

Нужно держать весь путь:


комментарий 1 (id=5 path=5)
комментарий 3 (id=12 path=5.12)
комментарий 6 (id=17 path=5.12.17)
комментарий 8 (id=25 path=5.12.17.25)
комментарий 7 (id=20 path=5.12.20)
комментарий 4 (id=13 path=5.13)
комментарий 2 (id=7 path=7)
комментарий 5 (id=16 path=7.16)

Немного простого кода для работы с путём.

Можно даже от ID отказаться

DeveloperRu
На сайте с 27.02.2009
Offline
72
#10

остался вопрос с выборкой первых 10ти комментов уровня 0 и неограниченного кол-ва комментов, которые являются детьми этих 10

нестед позволяет это сделать ?

Ответы на вопросы (http://telenok.com)
12

Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий