2011-03-20 113 views
2

在你大喊ORDER BY id之前,情況完全不同。按照最新回覆時間安排論壇帖子

我被要求提供的論壇是留言板論壇,未註冊的用戶可以回覆併發帖。對帖子的回覆在被回覆的帖子下縮進。當然,這些都在無序列表中。簡單例子:

  • 主交
    • 回覆後
      • 甲答覆的答覆
    • 另一個答覆主
  • 有無關的答覆

這像什麼Nettuts+的評論系統看起來像一個職位。在數據庫中,一個帖子包含所有明顯的東西(id,消息體,作者,時間...)和一個回覆。 replyid基本上意味着這篇文章的回覆是什麼。如果replyid是0,它是一個主要的帖子(在普通的論壇意味着線程)。

這就是我如何去顯示這些帖子:首先,我調用一個函數(讓我們稱之爲showPosts) replyid;默認值爲0.

在showPosts中,我從一個關聯數組中獲取與數據庫參數相同的所有帖子,並使用showPosts的結果填充數組中的posts字段,並將showPosts的id的帖子。在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 
+0

在大喊「在你喊之前」之前,你必須在這裏張貼一張表的結構。這是不重要的鄰接列表或什​​麼? – 2011-03-20 12:48:48

+0

'lastChanged'的想法是我想要建議的 - 當你說這是浪費內存或時間殺手,你是什麼意思?把這個列設置爲'ORDER BY'對我來說聽起來像是一個定時器,而不是每次都要計算帖子的順序。 – 2011-03-20 12:57:26

+0

@Sam Starling - 通過時間殺手我的意思是說,每當用戶保存帖子時,您都必須在回覆鏈上走上頂部,並在每一步中更新一個字段。後來這是節省時間,但我有點擔心最初的執行。 – Zirak 2011-03-20 13:02:45

回答

0

如果你不想與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; 
} 
+0

我有一個類似的解決方案,並在[array_walk_recursive](http://php.net/array-walk-recursive)看看,但經過一些嘗試使我感到慌亂,完全失敗。你有什麼方向或建議開始寫你所建議的? – Zirak 2011-03-20 13:40:16

+0

您不必走數組,只需從遞歸底部返回最近的日期。 – Pentium10 2011-03-20 13:44:34

0

鑑於自己和Zirak之間的原始問題的評論,我提出以下的答案。

他說得對 - 遍歷整棵樹以找到最新評論的日期可能需要一段時間,因爲似乎對系統中可能發生的嵌套層數沒有限制。我知道這是很多重複的數據,但爲什麼不存儲類似main_post_id的內容,它指的是根節點(主文章)。那樣你可以ORDER BY max(time) WHERE main_post_id = 1

如果它是論壇軟件(因此我認爲它也可能涉及諸如線程列表分頁之類的事情),那麼這將使生活變得更容易,因爲您可以在數據庫查詢級別執行排序,而不是在PHP。

0

嗯..考慮到讀取列表比寫更多的時候執行。並且考慮到閱讀涉及更多的數據,我寧願在寫入時間上加載負載。

使用根層上的lastChanged解決方案,您還可以通過簡單的SQL查詢來讀取更少的行,而不是讀取x行數的列表。

Sams解決方案的缺點是,您需要額外的GROUP BY,這會導致臨時表,從而降低您的SQL Server的速度。