确定论坛中的未读项目

时间:2009-02-05 01:55:31

标签: php mysql forum

使用PHP和MySQL,我有一个我正在尝试构建的论坛系统。我想知道的是,我如何设置它,以便当用户阅读论坛条目时,无论他们在哪个论坛,它都显示为该用户的JUST,直到有人在其上发帖。

目前,对于每个线程,我有一个带有PostID的表,并且具有发布它的UserID,将其链接到的ThreadID,实际的Post(作为Text),然后是它发布的日期/时间。 / p>

对于每个论坛中的主题列表,都有threadID(主键),ThreadName,它所属的ForumID,NumPosts,NumViews,LastPostDateTime和CreateDateTime。有什么帮助吗?

7 个答案:

答案 0 :(得分:8)

传统的解决方案是join table类似于以下内容:

CREATE TABLE topicviews (
    userid INTEGER NOT NULL,
    topicid INTEGER NOT NULL,
    lastread TIMESTAMP NOT NULL,
    PRIMARY KEY (userid, topicid),
    FOREIGN KEY (userid) REFERENCES users(id),
    FOREIGN KEY (topicid) REFERENCES topics(id)
);

每次读取主题时都会更新lastread。当显示主题列表时,如果topics.lastupdated是> topicviews.lastread,有新帖子。

传统的解决方案是垃圾,会杀死你的数据库!不要这样做!

第一个问题是,对每个主题视图的写入很快就会使数据库服务器在繁忙的论坛上瘫痪,特别是在只有表级锁的MyISAM表上。 (不要使用MyISAM表,将InnoDB用于除全文搜索之外的所有内容。)

您可以稍微改善这种情况,只需在主题中读取实际新消息时写入最后读取时间。如果topic.lastupdated< topicviews.lastread更新值没有任何好处。即便如此,在一个频繁使用的论坛上,这可能是一种负担。

第二个问题是组合爆炸。每个用户每个主题一行很快就会加起来:只有一千个用户和一千个主题,你可能有一百万个topicview行要存储!

您可以通过限制每个用户记住的主题数量来改善这种情况。例如,当它超过某个年龄时,您可以从视图表中删除任何主题,并假设所有旧主题都是“已读”。这通常需要在后台完成清理任务。

其他不太密集的方法包括:

  • 每个论坛仅存储一个最后读取时间
  • 仅在整个网站上存储每个用户的一个lastvisit时间,这将显示为“新”仅自用户上次访问(会话)以来更新的内容
  • 根本不存储任何lastread信息,但包括主题URL本身的最后更新时间。如果用户的浏览器最近看过该主题,它将记住该URL并将其标记为已访问。然后,您可以使用CSS将访问过的链接设置为“不包含新消息的主题”。

答案 1 :(得分:3)

当用户读取该线程时,可能存储在另一个表UserID,threadID,LastReadDateTime中。

if (LastPostDateTime > LastReadDateTime) you got an unread post.

可悲的是,你有很大的开销,每次阅读都会有写作。

答案 2 :(得分:2)

这里的一般想法是正确的,但他们忽略了可伸缩性问题的一些明显的解决方案。

  

@bobince:   第二个问题是组合爆炸。每个用户每个主题一行很快就会加起来:只有一千个用户和一千个主题,你可能有一百万个topicview行要存储!

如果有人没有查看过该主题,您无需在“topicviews”表中存储记录。如果返回null,或者last_read时间是< last_post时间。这将使“百万”行减少一个数量级。

  

@gortok:有很多方法可以做到这一点,但随着用户访问网站,每个方法都会呈指数级增长。

在这种情况下,您可以在n-posts或n-weeks之后归档论坛,并在锁定时清理“topicviews”表。

我的第一个建议是显而易见的,没有任何缺点。我的第二个减少了归档主题的可用性,但这对于快速论坛来说是一个很小的代价。缓慢的论坛只是阅读和发布的痛苦。

但老实说?您可能不需要担心可伸缩性。甚至一百万行真的不是那么多。

答案 3 :(得分:1)

没有简单的方法可以做到这一点。有很多方法可以做到这一点,但随着用户访问网站,每个方法都会呈指数级增长。您可以做的最好并且仍然保持性能的是拥有时间戳并将自上次访问以来已更新的任何论坛标记为“未读”。

答案 4 :(得分:1)

您可以使用用户浏览器的功能,并将最后一个postid附加到线程的链接中,如下所示:“thread.php?id = 12& lastpost = 122”

通过在CSS中使用a:visit,您可以显示用户已阅读的帖子与他未阅读的帖子不同。

答案 5 :(得分:0)

Bobince有很多好建议。另外几个潜在的优化:

写下新的“这是新的吗?” memcached和MySQL“ARCHIVE”表的信息。批处理作业可以更新“真实”表。

对于每个用户,请保留“读取所有内容直至$ date”标记(单击“标记所有读取”时)。

当发布新内容时,清除所有“已被读取”的标志 - 这会使“标志”的数量保持不变,而表格可以是(topic_id,user_id) - 没有时间戳。

答案 6 :(得分:0)

使用功能用户的浏览器并在线程的链接中添加最后一个帖子ID。使用a:在CSS中访问后,您可以显示用户未读取的所有线程。