实施基本的Twitter / Facebook @mention系统

时间:2013-06-06 16:15:52

标签: php mysql regex database pdo

我正在尝试为我正在创建的微博应用程序创建一个基本的@mention系统(这是我学习PDO的项目)。

我读了一些其他similar questionsthreads,但我仍然无法理解每个人的言论。

我目前拥有的是数据库结构,如下所示:

**mentions:** <br>
mention_id (primary key auto increment) <br> 
post_id (id from the posts table) <br> 
user_id (id of the user who is mentioned) <br>
unread (either 0 or 1 depending on whether the post has been viewed by the user mentioned)

**posts:** <br>
post_id (primary key auto increment) <br> 
user_id (id of the user who posted) <br> 
post_content (the post contents)<br> 
stamp (the post time stamp)

我认为它必须基于以前的帖子工作的方式是这样的 - 我们将帖子添加到数据库然后在其上运行一个函数来获取post_id然后我们对它运行一个正则表达式语句并提取所有引用到@something,然后我们切断@符号并通过一个函数运行它来检查是否有一个用户名。如果有一个名称的用户,我们将他们的user_id,post_id和一个1插入未读的列到数据库的提及表中,以便稍后我们可以检查我们当前登录的用户是否有任何未读的提及并显示这些。我知道这种方法可能无法很好地扩展,但我并不是在考虑拥有数百万用户,而只是想要一个简单的解决方案。

所以...我正在寻找的是有人看看我到目前为止所拥有的东西,让我知道如何让它发挥作用和/或建议一个更好/更简单的方法。

我想要的最终结果是用户能够@mention另一个用户并能够将其显示为“未读”提及,直到所述用户查看他们的通知(提及的列表等,例如Facebook) 。

到目前为止我所拥有的是:

$post_content = 'Yo @jack, what up? I have a new email, jack@bob.com'; 
// to be later replaced with $post_content = $_POST['post_content'];

// right here would be a function add_post that
// inserts the post_content, user_id and time stamp into the database

function select_post($post_content){
    $sql = "SELECT 
              post_id
            FROM posts
            WHERE post_content = $post_content
          "; 
    $stmt = $GLOBALS['db']->prepare($sql); 
    $stmt->execute(); 
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    return $rows;
}

function valid_username($mentionedUser){
    $sql = "SELECT 
              username
            FROM users
            WHERE username = $mentionedUser
          "; 
    $stmt = $GLOBALS['db']->prepare($sql); 
    $stmt->execute(); 
    $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
    return $rows;
}

function insert_mention($post_id, $mentionedUser){
    $sql = "INSERT INTO 
            mentions (post_id, user_id, unread)
            VALUES (:post_id, :user_id, 1) // 1 means unread
            ";
    $stmt = $GLOBALS['db']->prepare($sql);                                      
    $stmt->bindParam(':user_id', $mentionedUser, PDO::PARAM_STR);       
    $stmt->bindParam(':post_id', $post_id, PDO::PARAM_INT);    
    $stmt->execute();
}

add_post($userid, $post_content);
$post_id = select_post($post_content);

if (preg_match("/\B@[a-zA-Z0-9]+/i", $post_content)) {

    preg_match_all("/\B@[a-zA-Z0-9]+/i", $post_content, $mentions);
    $mentions = array_map(function($str){ return substr($str, 1); }, $mentions[0]);
    foreach($mentions as $mentionedUser){
        if(!valid_username($mentionedUser)){ continue; }
        insert_mention($post_id, $mentionedUser);   
    }

我是否在正确的轨道上?我怎样才能做到这一点?请问,你的答案中的细节越多越好,我对你使用的语法感兴趣,而不仅仅是一般概述。

1 个答案:

答案 0 :(得分:0)

首先不要选择发帖内容来获取帖子ID!你必须做相反的事情! (从帖子ID中选择内容) 你必须做什么:

Get post content from any source (hardcoded, user input)
Insert it in database.
post-id = Get last inserted id
get all mentions
foreach mention,  then 
     get the mentionned user
     insert it in database
Done

我不会为你写的,但我建议你单独检查一下: 插入帖子 提取提及(print_r将显示$ mentions包含的内容,因此请将其用于调试) 插入提及参考。

我认为你如何使用$ mentions变量的内容存在问题。

同样,valid_username不会返回布尔值,但是你正在使用它(如果(!...))所以也许你的逻辑很糟糕(至少是函数名/内容/用法)

对于您使用的每个函数,请检查http://php.net/docs.php相信我,它会通过了解您使用的逻辑背后的逻辑帮助您制作更多的逻辑代码。