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
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>';
else
return $matches[0];
}, $string);
This is where regular expressions come in.
<?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
}
}
?>
/
at beginning and end are delimiters (don't worry about these for now).\w
stands for a word character, which includes a-z
, A-Z
, 0-9
, and _
.(?<!\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.\w+
means, "One or more word characters." The +
is known as a quantifier.\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.
Consider to use the Twitter API for catching the username from your text: https://github.com/twitter/twitter-text-js
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...