CodeIgniter's highlight_phrase() function, in the Text Helper library, looks like this:

 * Phrase Highlighter
 * Highlights a phrase within a text string
 * @access  public
 * @param   string  the text string
 * @param   string  the phrase you'd like to highlight
 * @param   string  the openging tag to precede the phrase with
 * @param   string  the closing tag to end the phrase with
 * @return  string
if ( ! function_exists('highlight_phrase'))
    function highlight_phrase($str, $phrase, $tag_open = '<strong>', $tag_close = '</strong>')
        if ($str == '')
            return '';

        if ($phrase != '')
            return preg_replace('/('.preg_quote($phrase, '/').')/i', $tag_open."\\1".$tag_close, $str);

        return $str;

However, the string I need to run it on is already fully-formatted HTML. What modification can I make to the preg_replace() so that it will not do replacements inside < and > tags. For example, if I were to pass in <a href="http://www.daniweb.com">Foo</a> as the string, and daniweb as the phrase to be wrapped, I don't want it to turn it into <a href="http://www.<strong>daniweb</strong>.com">Foo</a>. It should only work on text between > and <.

5 Years
Discussion Span
Last Post by Dani

I used this in js:

"(?!<[^>]*?)" + myWord + "(?!([^<]*?>))"

to avoid highlighting in attributes. It looks if it is within tags, nothing more. Seems to work the same in PHP.

Sorry to post this here, but I can no longer CTRL+V to paste in Opera.

Edited by pritaeas: Addon


pritaeas, did you by any chance have your < and > in reverse??

This is what ended up working for me ...

function highlight_search($string)
    $query = fetch_search_query();

    if (!empty($query))
        $replace = array();
        $with = array();

        foreach (explode(' ', $query) as $key => $query_word)
            $with[] = '<strong class="search">\1</strong>';
            $replace[] = "|(?![^<]+>)(\b$query_word\b)(?![^<]+>)|iu";

        return preg_replace($replace, $with, $string);

    return $string;

I stole the regex from CakePHP's highlight function, and then added in to check for word boundaries so that it would only match whole words.

Votes + Comments
Thanks for sharing.

Well... not sure, I had to type it over, because the copy-paste didn't work at the time, and it's been over two years since I wrote that.


No worries. Sorry about the Ctrl+V thing not working for a few hours.

This question has already been answered. Start a new discussion instead.
Have something to contribute to this discussion? Please be thoughtful, detailed and courteous, and be sure to adhere to our posting rules.