Bolding a keyword if found in a string

$keywords1 = array("stack","stack overflow");
$keywords2 = array("stack overflow","stack");
$str1 = "stack overflow";
$str2 = "stack overflow";
foreach($keywords1 as $kw){
    if (preg_match("~\b$kw\b~i", $str1)) {
        $str1 = str_replace($kw,'<b>'.$kw.'</b>',$str1);
foreach($keywords2 as $kw){
    if (preg_match("~\b$kw\b~i", $str2)) {
        $str2 = str_replace($kw,'<b>'.$kw.'</b>',$str2);
echo $str1;
echo "<br>";
echo $str2;


Greetings, Actually I want to bold a keyword if it is found in a string. I am using php preg_match() method for this purpose. My keywords are stored in an array and by iterating through each keyword I match it with my string and then bold it. I am facing a problem here. Both of the above strings are giving me different outputs. str1 is giving me stack overflow while str2 is giving me stack overflow. But for both cases both of the words should be bold. Please give me the solution to solve this problem.

I have this issue on

Nope, this is working correctly.

You are modifying the string as you find a match. Therefore, once you have matched stack in stack overflow, the string no longer says stack overflow. It now contains<b>stack</b> overflow. You aren’t testing for that.

There is no one solution. I can think of a couple off the top of my head but can’t give you the solution because I don’t know which one would work best for you.

1: Instead of modifying $str1, make a copy of it and modify the copy. Technically, in this case, you would still match both stack and stack overflow but you would still end up with a mess.

2: Sort the array largest to smallest and search for the largest entries first. This woudl allow you to bold stack and stack overflow BUT you are going to end up with <b><b>stack</b> overflow</b>.

3: Best answer, de-dupe your array before you start matching. More difficult but overall the best solution.


testing the performances and having clean the code, there is a simplest way to do without using any loop:

$string = "overflow bla bla stack overflow bla bla back over bla ack bover bla bla ack over bla bla stack 123 stack";

$wordToHighlight = array("stack","stack overflow", "ack", "ack over");

// Order array by number of spaces decreasing for a correct replacement
usort($wordToHighlight, function($a, $b){
    return substr_count($b, " ") - substr_count($a, " ");

// Preparing the $replace array with the tag to prefix and suffix
$replace = preg_filter('/^/', ' <b>', $wordToHighlight);
$replace = preg_filter('/$/', '</b> ', $replace);

// Preparing the $pattern array with the replacement text with tag and add conditions of spaces (start|end)
$pattern = preg_filter('/^/', '/((\s|^)', $wordToHighlight);
$pattern = preg_filter('/$/', '(\s|$))/', $pattern);

$myNewString =  preg_replace($pattern, $replace, $string);

echo $myNewString;
1 Like