16

個人的なプロジェクトでは、PHP と MySQL を使用してフォーラムを構築する必要があります。ビルド済みのフォーラム パッケージ (phpBB など) を使用することはできません。

私は現在、そのようなアプリケーションを構築するために必要なロジックに取り組んでいますが、長い 1 日であり、ユーザーの未読投稿を処理するという概念に苦労しています。私が持っていた1つの解決策は、基本的にすべての投稿IDとユーザーIDを保持する別のテーブルを用意して、それらが読み取られたかどうかを判断することでした:

tbl_userReadPosts: user_id, post_id, read_timestamp

明らかに、ユーザーの ID がこのテーブルに表示されていれば、そのユーザーが投稿を読んだことがわかります。これは素晴らしいことですが、1 日あたり数千の投稿 (提案されているシステムでは可能な数を超えています) と数千のユーザーがいる場合を除きます。このテーブルは、数時間ではないにしても、数日で巨大になります。

もう 1 つのオプションは、ユーザーの最後のアクティビティをタイムスタンプとして追跡し、最後のアクティビティが更新された後に行われたすべての投稿を取得することです。これは理論的には機能しますが、ユーザーが非常に長い投稿を書いているとしましょう。その間に、何人かのメンバーが新しいスレッドを開始したり、他のスレッドの投稿に返信したりします。ユーザーが新しい投稿を送信すると、最後のアクティビティが更新されるため、その間に行われたアクティビティと一致しません。

誰もこれを経験したことがありますか?どのように対処しましたか?

私は phpBB をチェックインしましたが、システムが各ユーザーにカスタム セッションを割り当て、それに基づいて動作しているようですが、これが未読の投稿をどのように処理するかについてのドキュメントはかなりまばらです。

いつものように、感謝して受け取った考えや意見。

4

5 に答える 5

7

すべての user_id と post_id を保持するテーブルは、指数関数的に大きくなるため、お勧めできません。フォーラム ソリューションが 100 万件の投稿と 50,000 人のユーザーに成長したとします。現在、500 億のレコードがあります。それは問題になります。

秘訣は、あなたが言ったようにテーブルを使用することですが、最後のログインとこ​​のログインの間に投稿された投稿のうち、このログイン以降に読み取られた投稿のみを保持します。

最後のログイン前に作成されたすべての投稿は、既読と見なされます。

IE さん、最後にログインしたのは 2011 年 4 月 3 日で、今日ログインしました。2011 年 4 月 3 日より前に作成されたすべての投稿は既読と見なされます (私にとっては目新しいものではありません)。2011 年 4 月 3 日から現在までのすべての投稿は、既読テーブルに表示されない限り未読です。ログインするたびに、読み取りテーブルがフラッシュされます。

このようにして、read posts テーブルには、メンバーごとに 200 を超えるレコードが含まれないようにする必要があります。

于 2011-04-05T15:53:48.107 に答える
7

素早い回答で申し訳ありませんが、私には 1 秒しかありません。既に推測したように、読み取り情報をデータベースに保存したくないのは間違いありません。このテーブルは巨大になります。

あなたがすでに提案したことの間の何か: ユーザーの最後のアクティビティを保存し、Cookie で見たものの情報を保存することと組み合わせて、ユーザーが既に読んだスレッド/投稿を判断します。

これにより、ストレージがクライアント側の Cookie にオフロードされ、はるかに効率的になります。

于 2011-04-05T15:52:12.487 に答える
3

post*user ごとに新しい行を作成する代わりに、user-table に、ユーザーが読み取った post-ID を含むカンマ区切りの文字列を保持するフィールドを作成できます。

明らかに、ユーザーは 2 年前の未読の投稿があることを知る必要がないため、過去 24 時間以内に作成された投稿の「新しい投稿」のみを表示し、カンマ区切りの文字列には含まれません。

セッション変数または Cookie を使用してこれを解決することもできます。

于 2011-04-05T16:32:29.257 に答える
2

このメソッドは、最近アクセスpostIDしたものを ごとに個別に保存しますforumID

各投稿を個別に追跡するソリューションほどきめ細かくはありませんが、ユーザーごとに保存する必要があるデータの量を縮小し、ユーザーの閲覧履歴を追跡する適切な方法を提供します.

<?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;
?>

注:明らかに、この例はデモンストレーションのみを目的としています。実際のデータベースを扱う場合、構造とロジックの一部を変更する必要がある場合があります。

于 2011-04-05T21:38:57.617 に答える
1

Phpbb2 はこれをかなり簡単に実装しました。前回のログイン以降のすべての投稿が表示されるだけです。この方法では、ユーザーが実際に見たり読んだりした内容に関する情報を保存する必要はありません。

于 2011-04-07T18:28:43.843 に答える