2011-03-20 162 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的速度。