Reputation: 4701
I have a variable $text
which is a plain text that can contain one or more email addresses in a line of text. I use a regular expression to find these email addresses and then transform them into clickable <a href="mailto:....etc
addresses. This is my code with an example that work fine:
$text = "this is the text that has a [email protected] in it and also [email protected].";
if(preg_match_all('/[\p{L}0-9_.-]+@[0-9\p{L}.-]+\.[a-z.]{2,6}\b/u',$text,$mails)){
foreach($mails[0] as $mail ){
$text = str_replace($mail,'<a href="mailto:'.$mail.'">'.$mail.'</a>',$text);
}
}
Or see this live demo. Problems occur when in my variable $text
there are two email adresses that have an exact (partial) match. For example [email protected]
and [email protected]
. Here's another live demo. The problem is the string replace happens within the partial match as well (because it is also a full match). How to bypass this issue?
Upvotes: 1
Views: 168
Reputation: 351
Like so...
<?php
$string = "this is the text that has a [email protected] in it and also [email protected].";
$search = array ( "!(\s)([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})!i",
"!^([_\.0-9a-z-]+@([0-9a-z][0-9a-z-]+\.)+[a-z]{2,3})!i" );
$replace = array ( "\\1<a href=\"mailto:\\2\">\\2</a>",
"<a href=\"mailto:\\1\">\\1</a>" );
echo preg_replace ( $search, $replace, $string );
?>
result...
this is the text that has a <a href="mailto:[email protected]">[email protected]</a> in it and also <a href="mailto:[email protected]">[email protected]</a>.
Upvotes: 1
Reputation: 3968
Why not use preg_replace
?
str_replace
can overwrite previous matches.
This should be good for you:
echo preg_replace(
'/([\p{L}0-9_.-]+@[0-9\p{L}.-]+\.[a-z.]{2,6}\b)/u',
'<a href="mailto:$1">$1</a>',
$text
);
Notice that I had to slightly modify the regular expression and wrap it in parentheses.
This is so that I can reference it in the replacement.
Upvotes: 2
Reputation: 654
You have to catch the caracter before your match to be sure it's a full match :
if(preg_match_all('/(.)([\p{L}0-9_.-]+@[0-9\p{L}.-]+\.[a-z.]{2,6}\b)/u',$text,$mails))
-----------------------------------^
Then you just have to modify a bit your str_replace parameter
var_dump($mails);
$id = 0;
foreach($mails[2] as $mail ){
$text = str_replace($mails[1][$id].$mail,'$mails[1][$id].<a href="mailto:'.$mail.'">'.$mail.'</a>',$text);
$id ++;
}
For example : https://3v4l.org/qYpHo
Upvotes: 1