PHP highlight keyword in string and maintain capitalisation

06 June, 2013 by Tom Elliott

Here’s a PHP function for a keyword search that will highlight all occurrences of a single keyword in a text string, whilst maintaining correct capitalisation.

The simple keyword highlight

Previously I used this simple snippet, that highlighted the searched word in a string. It uses inline styling for the highlight.

<?php

$str = "The monkey hangs on the door"
$keyword = "the"
echo str_ireplace($keyword, '<span style="color: #daa732;">'.$keyword.'</span>', $str);

?>

The problem with this approach was that the resulting highlighted term uses the capitalisation of the search word, rather than the case of the original string. In the example above, the first word ‘The’ in the string would appear as a lower-case ‘the’

A better keyword highlighting function

To solve this capitalisation problem, I created the below function which basically loops through all occurrences of the keyword within a string, forming a new highlighted string whilst maintaining the original capitalisation of the matched words it finds. It does this using a series of PHP string manipulation functions.

<?php

$string = "The monkey hangs from the door";
$keyword = "the";

function highlightkeyword($str, $search) {
	$highlightcolor = "#daa732";
	$occurrences = substr_count(strtolower($str), strtolower($search));
	$newstring = $str;
	$match = array();

	for ($i=0;$i<$occurrences;$i++) {
		$match[$i] = stripos($str, $search, $i);
		$match[$i] = substr($str, $match[$i], strlen($search));
		$newstring = str_replace($match[$i], '[#]'.$match[$i].'[@]', strip_tags($newstring));
	}

	$newstring = str_replace('[#]', '<span style="color: '.$highlightcolor.';">', $newstring);
	$newstring = str_replace('[@]', '</span>', $newstring);
	return $newstring;

}

?>

That’s better, using this function, the matched keywords now have correct capitals.

Highlighted search words in a string

To break down what’s going on here:

  1. The parameter $occurrences counts how many instances of the keyword are in the string using substr_count. Since substr_count is not case sensitive, we first need to convert both string and search word to lower-case
  2. An array $match is defined to keep track of each matched keyword
  3. A for loop is defined to iterate through the number of instances the keyword appears in the string. The position in the string of the search word is calculated using stripos (case insensitive string position) and the matched word is picked out using substr and the length of the keyword. A new string is then formed using str_replace (this time case sensitive), appending the wildcard characters [#] and [@] around each matched word.
  4. These wildcard characters are then replaced by inline styling for the highlight. We don’t want to include the inline styles in the for loop, as the characters in the styling may match the keyword.
  5. The new string is then returned.

To use this function, simply pass the string as the first parameter and the search word as the second:

echo highlightkeyword($string, $keyword);

An obvious example of where you might need this highlighting function would be within a product search. The $keyword parameter would then become the search field name from the form, e.g. $_POST[‘keyword’] and the string would be whatever content you want highlighting such as the product title.



8 Comments

  • Sam says:

    Hi,

    That is quite a long winded way of doing it! You can use a back reference to preserve capitalisation. e.g. This does the same but is much cleaner:

    function highlightKeyword2($haystack, $needle, $color = ‘#F00’)
    {
    return preg_replace(“/($needle)/i”, sprintf(‘$1’, $color), $haystack);
    }

  • Sam says:

    … Your comment system stripped out the tags:

    function highlightKeyword2($haystack, $needle, $color = ‘#F00’)
    {
    return preg_replace("/($needle)/i", sprintf(‘<span style="color: %s">$1</span>’, $color), $haystack );
    }

  • Pierre de LESPINAY says:

    Tom, with your function

    “`php
    highlightkeyword($str, $search)
    “`

    span tag seems nested as many times as the number of occurrences in each location.

  • Arumugam says:

    Thank u so mach dude, It was working so good

  • Anjali says:

    thank you so much……….. 🙂

  • Johnson says:

    Kindly tell us if the keyword is a Array of below elements…

    $keyword = array(‘dot in’,’dot com’,’.in’);

    How did i modify your code?

  • none says:

    This completely breaks formating. No more line breaks, nothing.

  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    css.php