2011-04-05 15 views
16

में अपठित पदों को संभालना एक व्यक्तिगत प्रोजेक्ट के लिए, मुझे PHP और MySQL का उपयोग करके एक फ़ोरम बनाना होगा। मेरे लिए पहले से निर्मित फ़ोरम पैकेज (जैसे phpBB) का उपयोग करना संभव नहीं है।PHP/MySQL

मैं वर्तमान में इस तरह के एक एप्लिकेशन को बनाने के लिए आवश्यक तर्क के माध्यम से काम कर रहा हूं, लेकिन यह एक लंबा दिन रहा है और मैं उपयोगकर्ताओं के लिए अपठित पदों को संभालने की अवधारणा के साथ संघर्ष कर रहा हूं। एक उपयोगकर्ता के आईडी इस तालिका में प्रदर्शित होता है,

tbl_userReadPosts: user_id, post_id, read_timestamp

जाहिर है, हम: एक समाधान मैं था एक अलग तालिका जो अनिवार्य रूप से सभी पोस्ट आईडी और प्रयोक्ता आईडी रखती है, यह निर्धारित करने के लिए था कि अगर वे पढ़ कर दिया गया है पता है कि उन्होंने पोस्ट पढ़ लिया है। यह बहुत अच्छा है, सिवाय इसके कि हमारे पास प्रति दिन हजारों पद हैं (जो कि प्रस्तावित किया जा रहा है सिस्टम में संभव से अधिक है), और उपयोगकर्ताओं के thousdands। यह तालिका घंटों तक नहीं, दिनों के मामले में बड़ी हो जाएगी।

एक और विकल्प उपयोगकर्ता की आखिरी गतिविधि को टाइमस्टैम्प के रूप में ट्रैक करना होगा, और उसके बाद उनकी पिछली गतिविधि अपडेट होने के बाद किए गए सभी पोस्ट पुनर्प्राप्त करना होगा। यह सिद्धांत में काम करता है, लेकिन मान लें कि कोई उपयोगकर्ता एक बहुत ही लंबी पोस्ट लिख रहा है, और इस बीच कई सदस्य नए धागे भी शुरू करते हैं या अन्य धागे में पोस्ट का जवाब देते हैं। जब उपयोगकर्ता अपनी नई पोस्ट सबमिट करता है, तो उसकी आखिरी गतिविधि अपडेट की जाएगी, और इस प्रकार इस दौरान किए गए लोगों से मेल नहीं खाती।

क्या किसी के पास इसका अनुभव है, और आपने इसका सामना कैसे किया?

मैंने phpbb में चेक किया है और ऐसा लगता है कि सिस्टम प्रत्येक उपयोगकर्ता को एक कस्टम सत्र असाइन करता है, और उस आधार पर काम करता है, लेकिन दस्तावेज़ीकरण इस बात के बारे में बहुत स्पष्ट है कि यह अपठित पदों के साथ कैसे व्यवहार करता है।

विचार और विचार हमेशा के रूप में आभारी रूप से प्राप्त हुए।

उत्तर

6

त्वरित उत्तर के लिए खेद है, लेकिन मेरे पास केवल एक सेकंड है। आप निश्चित रूप से डेटाबेस में पढ़ने की जानकारी को संग्रहीत नहीं करना चाहते हैं, जैसा कि आप पहले से ही घटा चुके हैं, यह तालिका विशाल हो जाएगी।

जो कुछ आपने पहले ही सुझाया है उसके बीच कुछ है: उपयोगकर्ताओं को पिछली गतिविधि को स्टोर करें, और कुकी में जो कुछ देखा है, उसकी जानकारी संग्रहीत करने के संयोजन के साथ, यह निर्धारित करने के लिए कि वे पहले से कौन से थ्रेड/पोस्ट पढ़ चुके हैं।

यह क्लाइंट साइड कुकी में स्टोरेज को ऑफ़लोड करता है, जो कि अधिक कुशल है।

+0

मैंने सभी उत्तरदाताओं को उनके इनपुट के लिए +1 दिया। मुझे आपका सुझाव पसंद है, जॉन। मेरे पास इस विधि (या संयोजन, बल्कि) के साथ एक खेल होगा। धन्यवाद! – BenM

7

सभी उपयोगकर्ता_आईड्स और पोस्ट_ड्स रखने वाली एक तालिका एक बुरा विचार है, क्योंकि यह तेजी से बढ़ता है। कल्पना करें कि क्या आपका मंच समाधान दस लाख पदों और 50,000 उपयोगकर्ताओं तक बढ़ गया है। अब आपके पास 50 अरब रिकॉर्ड हैं। यह एक समस्या होगी।

यह चाल एक टेबल का उपयोग करने के लिए है जैसा आपने कहा था, लेकिन यह केवल उस पोस्ट को रखता है जो इस लॉगिन के बाद से पढ़ा गया है, जो अंतिम लॉगिन और इस लॉगिन के बीच पोस्ट किए गए थे।

अंतिम लॉगिन से पहले की गई सभी पोस्टों को पढ़ा जाता है।

आईई, मैंने अंतिम बार 4/3/2011 को लॉग इन किया था, और फिर मैं आज लॉग इन करता हूं। 4/3/2011 से पहले की गई सभी पोस्टों को पढ़ा जाता है (वे मेरे लिए नए नहीं हैं)। 4/3/2011 और अब के बीच की सभी पोस्ट अपठित हैं जब तक कि वे पढ़ने की तालिका में नहीं देखे जाते। जब भी मैं लॉग इन करता हूं, तब पढ़ने की तालिका फ़्लश होती है।

इस तरह आपकी पढ़ाई पोस्ट तालिका में प्रत्येक सदस्य के लिए कुछ सौ से अधिक रिकॉर्ड नहीं होने चाहिए।

3

प्रत्येक पोस्ट * उपयोगकर्ता के लिए एक नई पंक्ति रखने के बजाय, आपके पास उपयोगकर्ता-तालिका में एक फ़ील्ड हो सकती है जिसमें उपयोगकर्ता द्वारा पढ़े गए पोस्ट-आईडी के साथ अल्पविराम से अलग स्ट्रिंग होती है।

स्पष्ट रूप से उपयोगकर्ता को यह जानने की आवश्यकता नहीं है कि 2 साल पहले अपठित पोस्ट हैं, इसलिए आप पिछले 24 घंटों में किए गए पदों के लिए केवल "नई पोस्ट" प्रदर्शित करते हैं और अल्पविराम से अलग स्ट्रिंग में नहीं हैं।

आप इसे सत्र चर या कुकी के साथ भी हल कर सकते हैं।

2

यह विधि प्रत्येक 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; 
?> 

नोट: जाहिर है इस उदाहरण प्रदर्शन प्रयोजनों के लिए ही है। वास्तविक डेटाबेस से निपटने के दौरान संरचना और तर्क में से कुछ को बदलने की आवश्यकता हो सकती है।

1

Phpbb2 ने इसे काफी सरल बना दिया है। यह आपके अंतिम लॉगिन के बाद से आपको सभी पोस्ट दिखाता है। इस तरह आपको उपयोगकर्ता ने वास्तव में क्या देखा या पढ़ा है इसके बारे में कोई जानकारी स्टोर करने की आवश्यकता नहीं है।

0

कुछ ऐसा सुझाव नहीं दिया गया था जो उस प्रकार की जानकारी, अर्थात नोएसक्यूएल को स्टोर करने के लिए बिग डेटा का उपयोग कर रहा था। यह विशेष रूप से इस तरह के डेटा को संभालने के लिए प्रभावी ढंग से बनाया जाता है।

मैं मोंगोडीबी का उपयोग करता हूं लेकिन आप अपनी आवश्यकताओं के अनुरूप एक नोएसक्यूएल एप्लिकेशन पा सकते हैं। http://nosql.findthebest.com/

यह आपको अभी जो भी काम कर रहा है उसके बजाए अन्य लागू उपयोगों पर स्केल करने की अनुमति देगा। ईजी, फ़ोरम, पोस्ट, टिकट, नोट्स, संदेश इत्यादि।

एक और सुझाव यह है कि आप वैकल्पिक रूप से डेटा को "मेटाडाटा" के रूप में स्टोर कर सकते हैं, सीएसवी सुझाव के समान, लेकिन इसे अधिक लचीला और स्तरीय संरचना दे रहा है, अपने ऑब्जेक्ट को लोड करने के लिए डेटा को संपीड़ित करने और रन टाइम पर अनसुलझा करने के लिए धारावाहिक का उपयोग करना। इस प्रकार एक ऐसे सत्र की तरह काम करना जो समाप्त नहीं होता है जो session_id के बजाय user_id से जुड़ा हुआ है जिसे मांग पर लोड किया जा सकता है और फिर भी आपको अलग किया जा सकता है। उदाहरण के लिए जब किसी विशेष उपयोगकर्ता के लिए फ़ोरम पृष्ठ लोड किया जाता है।

जैसे:

(सूखी कोडित उदाहरण - अपने स्कीमा फिट करने के लिए समायोजित)

<?php 
/** 
array(
    "form_id1" => array("post_id1", "post_id2",), 
    "form_id2" => array("post_id1", "post_id2",) 
); 
*/ 

$this->user->metadata = unserialize(file_get_contents('/metadata/forums/' . $this->user->id)); 

if(!isset($this->user->metadata[$this->forum->id])){ 
    $this->user->metadata[$this->forum-id] = array(); 
} 
if(!in_array($this->post->id, $this->user->metadata[$this->forum->id])){ 
    $this->user->metadata[$this->forum-id][] = $this->post->id; 
} 
file_put_contents('/metadata/forums/' . $this->user->id, serialize($this->metadata);); 

आप अपने आरडीबीएमएस साथ file_x_contents बाहर स्वैप कर सकते हैं - उदाहरण के लिए:

<?php 
$getMetadata = "SELECT forums FROM user_metadata WHERE user_id = $this->user->id"; 
$dbrs = mysqli_query($getMetadata); 
$this->user->metadata = unserialize($dbrs['forums']); 
$dbrs->close(); 

$metadata = serialize($this->user->metadata); 
$saveMetadata = "UPDATE user_metadata SET forums = '$metadata' WHERE user_id = '$this->user->id'"; 
mysqli_query($saveMetadata); 

आप regexp के माध्यम से खोज जैसी अन्य चीजें भी कर सकते हैं, इसे आगे बढ़ाएं (विषय, श्रेणी, आदि), या पोस्ट पढ़ने वाले उपयोगकर्ताओं पर आधारित विधि को बदलें फ़ोरम में फ़ोरम (फ़ोरम-> पोस्ट-> देखी गई) फ़ोरम पोस्ट के बजाय उपयोगकर्ता को पढ़ा जाता है (उपयोगकर्ता-> मेटाडाटा-> फ़ोरम)। विशेष रूप से यदि आपके पास पहले से ही "कुल दृश्य" काम कर रहा है, लेकिन किसी विशेष उपयोगकर्ता द्वारा पढ़े गए पोस्ट को पुनर्प्राप्त करने में यह और अधिक कठिन होगा, जबकि रिवर्स अन्य विधि के साथ सत्य है, या संयोजन के दोनों तरीकों का भी उपयोग करना है ।