Im working on a commenting web application and i want to parse user mentions (@user) as links. Here is what I have so far:
$text = "@user is not @user1 but @user3 is @user4";
$pattern = "/\@(\w+)/";
preg_match_all($pattern,$text,$matches);
if($matches){
$sql = "SELECT *
FROM users
WHERE username IN ('" .implode("','",$matches[1]). "')
ORDER BY LENGTH(username) DESC";
$users = $this->getQuery($sql);
foreach($users as $i=>$u){
$text = str_replace("@{$u['username']}",
"<a href='#' class='ct-userLink' rel='{$u['user_id']}'>@{$u['username']}</a> ", $text);
}
$echo $text;
}
The problem is that user links are being overlapped:
<a rel="11327" class="ct-userLink" href="#">
<a rel="21327" class="ct-userLink" href="#">@user</a>1
</a>
How can I avoid links overlapping?
Answer Update
Thanks to the answer picked, this is how my new foreach loop looks like:
foreach($users as $i=>$u){
$text = preg_replace("/@".$u['username']."\b/",
"<a href='#' title='{$u['user_id']}'>@{$u['username']}</a> ", $text);
}
Problem seems to be that some usernames can encompass other usernames. So you replace
user1properly with<a>user1</a>. Then,usermatches and replaces with<a><a>user</a>1</a>. My suggestion is to change your string replace to a regex with a word boundary, \b, that is required after the username.