11

我现在正在制作一个新闻和评论系统,但我现在被困在一个部分上一段时间了。我希望用户能够以@username之类的 Twitter 风格引用其他玩家。脚本看起来像这样:(不是真正的 PHP,只是想象脚本;3)

$string = "I loved the article, @SantaClaus, thanks for writing!";
if($string contains @){ 
    $word = word after @;
    $check = is word in database? ...
}

而对于字符串中的所有@username,可能是用while() 完成的。我被卡住了,请帮忙。

4

4 回答 4

14

这就是正则表达式的用武之地。

<?php
    $string = "I loved the article, @SantaClaus! And I agree, @Jesus!";
    if (preg_match_all('/(?<!\w)@(\w+)/', $string, $matches))
    {
        $users = $matches[1];
        // $users should now contain array: ['SantaClaus', 'Jesus']
        foreach ($users as $user)
        {
            // check $user in database
        }
    }
?>
  1. /开头和结尾是分隔符(暂时不要担心这些)。
  2. \w代表单词字符,包括a-z, A-Z, 0-9, 和_.
  3. The(?<!\w)@有点高级,但它被称为否定的lookbehind assertion,意思是“@不跟随单词字符的一个”。这样您就不会包含电子邮件地址之类的内容。
  4. 意思是“\w+一个或多个单词字符”。被+称为量词
  5. 周围的括号\w+ 捕获带括号的部分,并出现在$matches.

正则表达式.info似乎是一个受欢迎的教程选择,但网上还有很多其他的。

于 2012-12-26T16:22:12.290 回答
6

看起来像是 preg_replace_callback() 的工作:

$string = preg_replace_callback('/@([a-z0-9_]+)/', function ($matches) {
  if ($user = get_user_by_username(substr($matches[0], 1)))
    return '<a href="user.php?user_id='.$user['user_id'].'">'.$user['name'].'</a>';
  else
    return $matches[0];
}, $string);
于 2012-12-26T16:15:36.927 回答
3

考虑使用 Twitter API 从文本中捕获用户名:https ://github.com/twitter/twitter-text-js

于 2012-12-26T16:26:24.527 回答
2

这是一个符合您需要的表达式,但不会捕获电子邮件地址:

$str = '@foo I loved the article, @SantaClaus, thanks for writing to my@email.com';
preg_match_all('/(^|[^a-z0-9_])(@[a-z0-9_]+)/i', $str, $matches);
//$matches[2][0] => @foo
///$matches[2][1] => @SantaClause

如您所见: my@email.com 未被捕获,但 @foo 和 @SantaClaus 字符串......

于 2012-12-26T16:33:19.030 回答