When a user posts a comment, I want to grab every word that starts with a @ symbol.
ex. string is 'Check this out @user1. It's a photo of @user2 and @user3.'
When I'm on the PHP side, I want to grab user1, user2, user3 so I can then notify those users that they have been tagged in this comment.
I tried playing with strpos, but closest I got was if the string started with @ using the logic below.
if (0 === strpos($string, '@')){ echo 'yes' }
but that wasn't what I needed.
You can simply use this function:
function get_tagged_users($comment) {
$matches = array();
if (preg_match_all('/@(\w+)\b/', $comment, $matches)) {
return $matches[1];
}
return array();
}
It will return an array of usernames (without "@") and an empty array if no matches found or if an error occurred while doing regex.
Note: It uses regular definition of word boundaries and words. Lorem @ipsum-ed dolor
will return just ipsum
.
So if you need to include hypen (-) in usernames, just change regex with /@([-\w]+)\b/
Here's a regex method of doing this:
$matches = [];
preg_match_all( "/@([-\w]+)\b/",
"Check this out @user1. It's a photo of @user2 and @user3",
$matches);
print_r($matches);
Output:
Array
(
[0] => Array
(
[0] => user1
[1] => user2
[2] => user3
)
)
The regular expression matches @
followed by one or more alphanumeric characters or an underscore (\w
) up to a word boundary (\b
). The matched words are in $matches
(as you may have guessed).
A "regex-free" and "explode-free" solution
$str = 'Check this out @user1. It\'s a photo of @user2 and @user3.';
$offset = 0;
$users = array();
$str .= ' ';
while($offset = strpos($str, '@', $offset + 1)){
$users[] = rtrim(substr($str, $offset + 1, strpos($str, ' ', $offset)- $offset), '?.,!:;');
}
print_r($users);
However this assumes that your usernames do not contain white space and punctuation characters as well as that a proper white space is present after punctuation.
I created a quick benchmark script to test which answer was the fastest. Contrary to my belief regex appears to be faster than bit-searching manually. You can see the results yourself here