Reputation: 23141
I want to add HTML tags to words that contain a search term AND I want to add nested tags around each occurrence of the search term.
Sample string:
$str = "i like programming very much";
Sample search term:
$word = "r";
Desired result:
i like <span class='pice1'>p<span class='pice2'>r</span>og<span class='pice2'>r</span>aming</span> <span class='pice1'>ve<span class='pice2'>r</span>y</span> much
I wrote the following regex for it, but it sometimes doesn't work.
$str = preg_replace(
"/([^\s{" . preg_quote($word) . "}]*?)(" . preg_quote($word) . ")([^\s{" . preg_quote($word) . "}]*)/siu",
"<span class='pice1'>$1</span><span class='pice2'>$2</span><span class='pice1'>$3</span>",
$str
);
Upvotes: -2
Views: 182
Reputation: 47874
To wrap whole words which contain the search term in a given HTML tag, use preg_replace_callback()
and have the regex pattern case-insensitively and unicode-safely match zero or more word character before and after the search term.
Once the whole word is isolated, search for the search term again and wrap each occurrence with another HTML tag. str_replace()
is not suitable for this inner replacement because it will not preserve the case of the matched search term.
Code: (Demo)
<style>
.whole_word {color: blue;}
.sub_word {color: red;}
</style>
<?php
$str = 'i like programming veRy much';
$find = 'r';
$safeFind = preg_quote($find);
$wordStart = '<span class="whole_word">';
$wordEnd = '</span>';
$partStart = '<span class="sub_word">';
$partEnd = '</span>';
echo preg_replace_callback(
"#\w*{$safeFind}\w*#iu",
fn($m) => $wordStart . preg_replace("#{$safeFind}#iu", $partStart . '\0' . $partEnd, $m[0]) . $wordEnd,
$str
);
Raw Output:
i like <span class="whole_word">p<span class="sub_word">r</span>og<span class="sub_word">r</span>amming</span> <span class="whole_word">ve<span class="sub_word">R</span>y</span> much
Rendered HTML
Upvotes: 0
Reputation: 23141
$str = "i like programming very much";
$word = "r";
function highlight($matches)
{
global $word;
return '<span class="pice1">'.str_replace($word,'<span class="pice2">'.$word.'</span>',$matches[0]).'</span>';
}
echo $str = preg_replace_callback("/([^\s]*?".preg_quote($word, '/')."[^\s]*)/siu", highlight, $str);
do the job(and it works with foreign languages too)...
Upvotes: 0
Reputation: 91385
What about this way :
$str = "i like programming very much";
$word = "r";
$list = explode(' ',$str);
for($i=0; $i<count($list); $i++) {
if(preg_match("/$word/", $list[$i])) {
$list[$i] = '<i>'.preg_replace("/$word/siu", "<b>$word</b>", $list[$i]).'</i>';
}
}
$str = implode(' ',$list);
echo $str,"\n";
Upvotes: 1
Reputation: 59451
$str = "i like programming very much";
$w = "r";
echo preg_replace("/($w)/", "<b>$1</b>", $str);
Output:
i like p<b>r</b>og<b>r</b>amming ve<b>r</b>y much
Answer to the comment: do it in two steps.
$str = "i like programming very much ready tear";
$w = "r";
$str = preg_replace("/\\b((?:\\w+|\\b)$w(\\w+|\\b))\\b/", "<i>$1</i>", $str);
$str = preg_replace("/($w)/", "<b>$1</b>", $str);
echo $str;
output:
i like <i>p<b>r</b>og<b>r</b>amming</i> <i>ve<b>r</b>y</i> much <i><b>r</b>eady</i> <i>tea<b>r</b></i>
Upvotes: 2
Reputation: 4502
Why dont't you just use str_replace()? I think it's more simple
$search = "ab";
$word = "ameriabank";
$newstr = "<span class=\"pice1\">".str_replace($search, $word, "</span><span class=\"pice3\">".$search."</span></span class=\"pice1>\")."</span>";
Upvotes: 3