Упорядочить сообщения форума по времени последнего ответа - PullRequest
2 голосов
/ 20 марта 2011

Прежде чем вы закричите ORDER BY id, ситуация совершенно иная.

Форум, который меня попросили создать, - это форум гостевой книги, на котором незарегистрированные пользователи могут отвечать и писать сообщения.Ответы к сообщению имеют отступ под сообщаемым сообщением.Конечно, это все в неупорядоченных списках.Краткий пример:

  • Главное сообщение
    • Ответ на сообщение
      • Ответ на ответ
    • Еще один ответ на главную
  • Aсообщение, которое не имеет ничего общего с ответами

Это похоже на то, как выглядит система комментариев Nettuts + .В базе данных у поста есть все очевидные вещи (идентификатор, тело сообщения, автор, время ...) и answerid.Ответ в основном означает, что это сообщение ответ.Если replyid равно 0, это основной пост (тема в обычном форуме означает.)

И вот как я обхожу отображение этих сообщений: сначала я вызываю функцию (назовем ее showPosts), которая имеет необязательныйparam называется replyid;по умолчанию 0.

В showPosts я получаю все сообщения с answerid, равным параметру из базы данных в ассоциативном массиве, и заполняю поле posts в массиве результатами showPosts, и я передаюпоказатьPosts идентификатор сообщения.В конце showPosts я возвращаю этот ассоциативный массив.Если это было неясно, вот фрагмент:

 function showPosts($postid = 0) {
        $query = query("SELECT * FROM posts WHERE replyid='$postid'");
        $r = array();
        $i = 0;
        while (@$row = $query->fetch_assoc()) {
            $r[$i] = $row;
            $r[$i]['posts'] = showPosts($row['id']);
            ++$i;
        }
        return $r;
    }

Все работает отлично, как и ожидалось, но я озадачен этой проблемой: когда пользователь отвечает на старый пост, я хочу, чтобы этот пост показывался первым,как в ветках форума.

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

Точно так же, как вы знаете, база данных MySQL и серверная часть написаны на php (и, конечно, взаимодействуют с MySQL с использованием MySQLi.)

Заранее спасибо, и извините, если что-нибудьнеясно.

Редактировать: Структура базы данных, как и требовалось.

id      |  int(11)
title   |  varchar(100)
author  |  varchar(100)
body    |  text
replyid |  int(11)
time    |  datetime

Ответы [ 3 ]

0 голосов
/ 20 марта 2011

Учитывая комментарии в исходном вопросе между мной и Зираком, я бы предложил следующий ответ.

Он прав - обход всего дерева для поиска даты последнего комментария может занять некоторое время, так как может показаться, что количество уровней вложенности, которые могут иметь место в системе, не ограничено. Я знаю, что это много повторений данных, но почему бы не сохранить что-то вроде main_post_id, которое относится к корневому узлу (основной пост). Таким образом, вы можете ORDER BY max(time) WHERE main_post_id = 1.

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

0 голосов
/ 20 марта 2011

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

С решением lastChanged на корневом уровне вы также можете сделать список с чтением гораздо меньшего количества строк с помощью простого SQL-запроса.чтения x чисел строк.

Недостатком решения Sams является то, что вам требуется дополнительная GROUP BY, которая приводит к временной таблице, которая замедляет работу вашего sql-сервера.

0 голосов
/ 20 марта 2011

Если вы не хотите идти с lastChanged

Вы должны вычислить последний раз последнего комментария в разделе отображения (в методе PHP, который вы опубликовали), а когда у вас есть для родительских сообщений дата последнего изменения, вы можете выполнить сортировку в массиве php.

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

как-то так (без сортировки)

function getPost($postid = 0) {
        $query = query("SELECT * FROM posts WHERE replyid='$postid'");
        $r = array();
        $i = 0;
        $recenttime=0;
        while (@$row = $query->fetch_array(MYSQLI_ASSOC)) {
            $r[$i] = $row;
            if (strtotime($row['time'])>$recenttime) {
                $recenttime=strtotime($row['time']);
            }
            $r[$i]['posts'] = $this->getPost($row['id']);
            if ($r[$i]['posts']['recenttime']>$recenttime) {
                $recenttime=$r[$i]['posts']['recenttime'];
            }
            ++$i;
        }
        $r['recenttime']=$recenttime;//save recenttime for this level
        if ($postid == 0) {
            // do the sort here based on $r[$i][$recenttime];
        }
        return $r;
}
...