Take the 2-minute tour ×

I'm making a news and comment system at the moment, but I'm stuck at one part for a while now. I want users to be able to refer to other players on the twitter style like @username. The script will look something like this: (not real PHP, just imagination scripting ;3)

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

And that for all the @username's in the string, perhaps done with a while(). I'm stuck, please help.

share|improve this question
Nothing wrong with a RegEx in this situation, you may want to check preg_match() –  Havelock Dec 26 '12 at 16:13
Rumor has it people call it pseudocode –  Alexander Dec 26 '12 at 21:36
@Alexander - I kinda like it though. Imagination scripting. "What do you do for work, Alex?" "Imagination scripting." O_o' –  acheong87 Dec 26 '12 at 22:06
add comment

4 Answers

up vote 13 down vote accepted

This is where regular expressions come in.

    $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. The / at beginning and end are delimiters (don't worry about these for now).
  2. \w stands for a word character, which includes a-z, A-Z, 0-9, and _.
  3. The (?<!\w)@ is a bit advanced, but it's called a negative lookbehind assertion, and means, "An @ that does not follow a word character." This is so you don't include things like email addresses.
  4. The \w+ means, "One or more word characters." The + is known as a quantifier.
  5. The parentheses around \w+ capture the portion parenthesized, and appear in $matches.

regular-expressions.info seems to be a popular choice of tutorial, but there are plenty of others online.

share|improve this answer
+1 For the explanation –  m4t1t0 Dec 26 '12 at 16:38
add comment

Looks like a job for 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>';
    return $matches[0];
}, $string);
share|improve this answer
+1 This certainly works, but will probably confuse newer developers. Maintainability is important. This can be done without obscure functions and without regular expressions. But 6 of one, half dozen the other. –  DampeS8N Dec 26 '12 at 16:18
I disagree. Regular expressions and functions (even anonymous) are nothing obscure. In fact I find this clearer (because the intention is immediately obvious to someone who knows the language) than your solution. –  AndreKR Dec 26 '12 at 16:24
I wish it was true that most code was maintained by people who understand the language. You may think it isn't your fault if your successors don't know the language, but all that will matter then is if they can understand the code or not. But I agree, everyone SHOULD know these things. –  DampeS8N Dec 26 '12 at 16:29
add comment

Consider to use the Twitter API for catching the username from your text: https://github.com/twitter/twitter-text-js

share|improve this answer
Maybe a bit heavyhanded for OP, but +1 for considering an existing solution. –  acheong87 Dec 26 '12 at 16:31
add comment

Here's an expression that'll match what you need, but won't capture email addresses:

$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

As you can see: my@email.com isn't captured, but the @foo and @SantaClaus strings are...

share|improve this answer
add comment

Your Answer


