【问题标题】:Handling unread posts in PHP / MySQL处理 PHP / MySQL 中的未读帖子
【发布时间】:2011-07-30 02:30:57
【问题描述】:

对于个人项目,我需要使用 PHP 和 MySQL 建立一个论坛。我无法使用已经构建的论坛包(例如 phpBB)。

我目前正在研究构建这样一个应用程序所需的逻辑,但这是漫长的一天,我正在为处理用户未读帖子的概念而苦苦挣扎。我有一个解决方案是有一个单独的表,它基本上包含所有帖子 ID 和用户 ID,以确定它们是否已被阅读:

tbl_userReadPosts: user_id, post_id, read_timestamp

显然,如果用户的 ID 出现在此表中,我们就知道他们已经阅读了该帖子。这很好,除非我们每天有成千上万的帖子(这在正在提议的系统中是不可能的),以及成千上万的用户。这张桌子会在几天甚至几小时内变得巨大。

另一种选择是将用户的上次活动作为时间戳进行跟踪,然后检索在上次活动更新后发布的所有帖子。这在理论上是可行的,但假设用户正在写一个非常长的帖子,同时几个成员也开始新线程或回复其他线程中的帖子。当用户提交他的新帖子时,他的最后一个活动将被更新,因此与同时进行的活动不匹配。

有没有人有这方面的经验,你是如何解决的?

我已经检查了 phpBB,似乎系统为每个用户分配了一个自定义会话,并在此基础上工作,但是关于如何处理未读帖子的文档非常稀少。

一如既往地感激地接受想法和意见。

【问题讨论】:

    标签: php mysql phpbb forums read-unread


    【解决方案1】:

    包含所有 user_ids 和 post_ids 的表是个坏主意,因为它会呈指数增长。想象一下,如果您的论坛解决方案增长到一百万个帖子和 50,000 个用户。现在您有 500 亿条记录。那会是个问题。

    诀窍是使用您所说的表格,但它仅包含自此登录以来已阅读的帖子,以及在上次登录和此登录之间发布的帖子。

    上次登录之前发布的所有帖子都被视为已读。

    IE,我上次登录是在 2011 年 4 月 3 日,然后我今天登录。 2011 年 4 月 3 日之前发布的所有帖子都被视为已读(它们对我来说并不新鲜)。从 2011 年 4 月 3 日到现在的所有帖子都是未读的,除非它们出现在已读表中。每次登录时都会刷新读取表。

    这样,您的已读帖子表中每个成员的记录不应超过几百条。

    【讨论】:

      【解决方案2】:

      很抱歉快速回答,但我只有一秒钟。您肯定不想将读取的信息存储在数据库中,正如您已经推断的那样,该表将变得巨大。

      介于您已经建议的内容之间:存储用户最近的活动,并结合存储他们在 cookie 中看到的内容的信息,以确定他们已经阅读了哪些线程/帖子。

      这会将存储卸载到客户端 cookie,效率更高。

      【讨论】:

      • 我给所有回答者一个 +1 的意见。我喜欢你的建议,约翰。我将尝试使用这种方法(或组合,更确切地说)。谢谢!
      【解决方案3】:

      您可以在用户表中拥有一个字段,该字段包含一个逗号分隔的字符串,其中包含用户已阅读的帖子 ID,而不是为每个帖子*用户创建一个新行。

      显然用户不需要知道有 2 年前的未读帖子,因此您只显示最近 24 小时内发布的帖子的“新帖子”,而不是逗号分隔的字符串。

      您也可以使用会话变量或 cookie 来解决此问题。

      【讨论】:

        【解决方案4】:

        此方法为每个forumID 分别存储最近访问的postID

        它不像单独跟踪每个帖子的解决方案那样精细,但它减少了您需要为每个用户存储的数据量,并且仍然提供了一种体面的方式来跟踪用户的查看历史记录。

        <?php
            session_start();
            //error_reporting(E_ALL);
        
            // debug: clear session
            if (isset($_GET['reset'])) { unset($_SESSION['activity']); }
        
            // sample data: db table with your forum ids
            $forums = array(
                //  forumID     forumTitle
                    '1'     =>  'Public Chat',
                    '2'     =>  'Member Area',
                    '3'     =>  'Moderator Mayhem'
            );
        
            // sample data: db table with your forum posts
            $posts = array(
                //  postID                  forumID     postTitle
                    '12345' =>  array(  'fID'=>'1', 'title'=>'Hello World'),
                    '12346' =>  array(  'fID'=>'3', 'title'=>'I hate you all'),
                    '12347' =>  array(  'fID'=>'1', 'title'=>'Greetings!'),
                    '12348' =>  array(  'fID'=>'2', 'title'=>'Car thread'),
                    '12349' =>  array(  'fID'=>'1', 'title'=>'I like turtles!'),
                    '12350' =>  array(  'fID'=>'2', 'title'=>'Food thread'),
                    '12351' =>  array(  'fID'=>'3', 'title'=>'FR33 V1AGR4'),
                    '12352' =>  array(  'fID'=>'3', 'title'=>'CAPSLOCK IS AWESOME!!!!!!!!'),
                    '12353' =>  array(  'fID'=>'2', 'title'=>'Funny pictures thread'),
            );
        
            // sample data: db table with the last read post from each forum
            $userhist = array(
                //  forumID     postID
                    '1'     =>  '12344',
                    '2'     =>  '12350',
                    '3'     =>  '12346'
            );
        
            // reference for shorter code
            $s = &$_SESSION['activity'];
        
            // store user's history into session
            if (!isset($s)) { $s = $userhist; }
        
            // mark forum as read
            if (isset($_GET['mark'])) {
                $mid = (int)$_GET['mark'];
                if (array_key_exists($mid, $forums)) {
                    // sets the last read post to the last entry in $posts
                    $s[$mid] = array_search(end($posts), $posts);
                }
                // mark all forums as read
                elseif ($mid == 0) {
                    foreach ($forums as $fid=>$finfo) {
                        // sets the last read post to the last entry in $posts
                        $s[$fid] = array_search(end($posts), $posts);
                    }
                }
            }
        
            // mark post as read
            if (isset($_GET['post'])) {
                $pid = (int)$_GET['post'];
                if (array_key_exists($pid, $posts)) {
                    // update activity if $pid is newer
                    $hist = &$s[$posts[$pid]['fID']];
                    if ($pid > $hist) {
                        $hist = $pid;
                    }
                }
            }
        
            // link to mark all as read
            echo '<p>[<a href="?mark=all">Read All</a>]</p>' . PHP_EOL;
        
            // display forum/post info
            foreach ($forums as $fid=>$finfo) {
                echo '<p>Forum: ' . $finfo;
                echo ' [<a href="?mark=' . $fid . '">Mark as Read</a>]<br>' . PHP_EOL;
                foreach ($posts as $pid=>$pinfo) {
                    if ($pinfo['fID'] == $fid) {
                        echo '- Post: <a href="?post=' . $pid . '">' . $pid . '</a>';
                        echo ' - ' . ($s[$fid] < $pid ? 'NEW' : 'old');
                        echo ' - "' . $pinfo['title'] . '"<br>' . PHP_EOL;
                    }
                }
                echo '</p>' . PHP_EOL;
            }
        
            // debug: display session value and reset link
            echo '<hr><pre>$_SESSION = '; print_r($_SESSION); echo '</pre>' . PHP_EOL;
            echo '<hr>[<a href="?reset">Reset Session</a>]' . PHP_EOL;
        ?>
        

        注意:显然这个例子只是为了演示目的。在处理实际数据库时,可能需要更改某些结构和逻辑。

        【讨论】:

          【解决方案5】:

          Phpbb2 的实现相当简单。它只显示自您上次登录以来的所有帖子。这样,您就不需要存储有关用户实际看到或阅读的任何信息。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-05-22
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多