Here's a different approach to search result keyword highlighting that will match all keyword sub strings in a case insensitive manner and preserve case in the returned text. This solution first grabs all matches within $haystack in a case insensitive manner, and the secondly loops through each of those matched sub strings and applies a case sensitive replace in $haystack. This way each unique (in terms of case) instance of $needle is operated on individually allowing a case sensitive replace to be done in order to preserve the original case of each unique instance of $needle.
<?php
function highlightStr($haystack, $needle, $highlightColorValue) {
// return $haystack if there is no highlight color or strings given, nothing to do.
if (strlen($highlightColorValue) < 1 || strlen($haystack) < 1 || strlen($needle) < 1) {
return $haystack;
}
preg_match_all("/$needle+/i", $haystack, $matches);
if (is_array($matches[0]) && count($matches[0]) >= 1) {
foreach ($matches[0] as $match) {
$haystack = str_replace($match, '<span style="background-color:'.$highlightColorValue.';">'.$match.'</span>', $haystack);
}
}
return $haystack;
}
?>
Descripción
Esta función devuelve una cadena o una matriz con todas las ocurrencias de busqueda en asunto (ignorando mayúsculas y minúsculas) sustituidas por el reemplazo dado. Si no necesita reglas de reemplazo sofisticadas, usted debería, por lo general, usar esta función en lugar de eregi_replace() o preg_replace() con el modificador i.
Lista de parámetros
- busqueda
-
Note: Cada reemplazo con la matriz busqueda es realizado en el resultado del reemplazo previo.
- reemplazo
-
- asunto
-
Si asunto es una matriz, entonces las búsquedas y reemplazos son realizados con cada entrada de asunto , y el valor devuelto es asimismo una matriz.
- conteo
-
El número de agujas coincidentes y reemplazadas será devuelto en conteo , que es pasado por referencia.
Si busqueda y reemplazo son matrices, entonces str_ireplace() toma un valor de cada matriz y los usa para realizar las búsquedas y reemplazos sobre asunto . Si reemplazo tiene menos valores que busqueda , entonces se usa una cadena vacía para el resto de valores de reemplazo. Si busqueda es una matriz y reemplazo es una cadena, entonces esta cadena de reemplazo es usada para cada valor de busqueda .
Valores retornados
Devuelve una cadena o una matriz de reemplazos.
Registro de cambios
| Versión | Descripción |
|---|---|
| 5.0.0 | El parámetro conteo fue agregado. |
Ejemplos
Example #1 Ejemplo de str_ireplace()
<?php
$etiqueta_body = str_ireplace("%body%", "black", "<body text=%BODY%>");
?>
Notes
Note: Esta función es segura con material binario.
str_ireplace
04-Dec-2008 03:28
01-Dec-2008 04:23
I found that many highlight string functions failed whilst performing a certain task on one of my projects.
$search="hi l";
$string="Hi-Level";
Because the str_ireplace function was looping through the two words ('hi' and 'l'), on the second loop it was replace the 'l' in 'class' and 'highlight' (not what you want)
This is what I have come up with
<?php
function highLight($needle,$haystack) {
$needle=trim($needle);
$wordsArray=explode(' ',$needle);
foreach($wordsArray as $key => $word) {
if(strlen(trim($word))!=0)
$haystack=str_ireplace($word,"***$word**",$haystack);
}
$haystack=str_replace("***","<span class=\"highlight\">",$haystack);
$haystack=str_replace("**","</span>",$haystack);
return $haystack;
}
echo highLight("hi l","Hi-Level");
// returns <span class="highlight">hi</span>-<span class="highlight">l</span>eve<span class="highlight">l</span>
function highLight_OLD($needle,$haystack) {
$needle=trim($needle);
$wordsArray=explode(' ',$needle);
foreach($wordsArray as $key => $word) {
if(strlen(trim($word))!=0)
$haystack=str_ireplace($word,"<span class=\"highlight\">$word</span>",$haystack);
}
return $haystack;
}
echo highLight_OLD($needle,$haystack);
// returns <span c<span class="highlight">l</span>ass="high<span class="highlight">l</span>ight">hi</span>-<span class="highlight">l</span>eve<span class="highlight">l</span>
?>
14-Nov-2008 02:44
This function will highlight search terms (Key Words in Context).
The difference between this one and the ones below is that it will preserve the original case of the search term as well. So, if you search for "american" but in the original string it is "American" it will retain the capital "A" as well as the correct case for the rest of the string.
<?php
function kwic($str1,$str2) {
$kwicLen = strlen($str1);
$kwicArray = array();
$pos = 0;
$count = 0;
while($pos !== FALSE) {
$pos = stripos($str2,$str1,$pos);
if($pos !== FALSE) {
$kwicArray[$count]['kwic'] = substr($str2,$pos,$kwicLen);
$kwicArray[$count++]['pos'] = $pos;
$pos++;
}
}
for($I=count($kwicArray)-1;$I>=0;$I--) {
$kwic = '<span class="kwic">'.$kwicArray[$I]['kwic'].'</span>';
$str2 = substr_replace($str2,$kwic,$kwicArray[$I]['pos'],$kwicLen);
}
return($str2);
}
?>
03-Oct-2008 02:29
If you want to keep the original capitalization when replacing some text (e.g. for highlighting the search-string in the the search result), you can use this code I wrote:
<?php
function ext_str_ireplace($findme, $replacewith, $subject)
{
// Replaces $findme in $subject with $replacewith
// Ignores the case and do keep the original capitalization by using $1 in $replacewith
// Required: PHP 5
return substr($subject, 0, stripos($subject, $findme)).
str_replace('$1', substr($subject, stripos($subject, $findme), strlen($findme)), $replacewith).
substr($subject, stripos($subject, $findme)+strlen($findme));
}
?>
Example for using:
<?php
$search = 'replaceme';
$text = 'Please RePlaCeMe, OK?';
// Will print "RePlaCeMe" with red color, but after this it would be "replaceme", not "RePlaCeMe"
$replace = '<font color="#FF0000">'.$search.'</font>';
echo str_ireplace($search, $replace, $text);
// Will print "RePlaCeMe" with red color
$replace = '<font color="#FF0000">$1</font>';
echo ext_str_ireplace($search, $replace, $text);
?>
02-Oct-2008 05:32
Example for str_ireplace(). It will print "RePlaCeMe" in red color, but after this, it would be written in lower case because of the string $search.
<?php
$search = 'replaceme';
$replace = '<font color="#FF0000">'.$search.'</font>';
$text = 'Please RePlaCeMe, OK?';
echo str_ireplace($search, $replace, $text);
?>
Example for ext_str_ireplace(). It will print "RePlaCeMe" in red color, and will not change the capitalization:
<?php
$search = 'replaceme';
$replace = '<font color="#FF0000">$1</font>';
$text = 'Please RePlaCeMe, OK?';
echo ext_str_ireplace($search, $replace, $text);
?>
10-Aug-2008 09:41
I'm really sorry, there is a big bug in my previous mb_str_ireplace function: here's the correct one:
<?php
/**
* Case insensitive multi-byte safe str_ireplace
* @param string $search
* @param string $replace
* @param string $subject
* @param int $count
* @param string $encoding
* @return string
*/
function mb_str_ireplace($search, $replace, $subject, $count = null, $encoding = u8) {
$l1 = mb_strlen($search, $encoding);
$l2 = mb_strlen($replace, $encoding);
$rc = 0;
$offset = 0;
while(ok($p = mb_stripos($subject, $search, $offset, $encoding)) && (is_null($count) || $rc <= $count)) {
if (ok($p))
$subject = mb_substr($subject, 0, $p, $encoding) . $replace . mb_substr($subject, $p + $l1, mb_strlen($subject, $encoding), $encoding);
$offset = $p + $l2;
$rc++;
}
return $subject;
}
?>
To make it mb_str_replace - change stripos to strpos. I'm sorry for previous bug, well, this one is tested.
I wonder should I publish my growing mb_ functions library like WORKING mb_wordwrap WITHOUT regexes (faster)... E-mail me.
06-Aug-2008 12:07
It's obvious str_ireplace() won't be multi-byte safe. Function mb_str_ireplace() is missing in php, so here's mine:
<?php
/**
* Case insensitive multi-byte safe str_replace
* @param string $search
* @param string $replace
* @param string $subject
* @param int $count
* @param string $encoding
* @return string
*/
function mb_str_ireplace($search, $replace, $subject, $count = null, $encoding = 'utf-8') {
$l1 = mb_strlen($search, $encoding);
$rc = 0;
$offset = 0;
while (ok($p = mb_stripos($subject, $search, $offset, $encoding)) && (is_null($rc) || $rc <= $count)) {
if (ok($p)) $subject = mb_substr($subject, $offset, $p, $encoding) . $replace . mb_substr($subject, $p + $l1, mb_strlen($subject, $encoding), $encoding);
$offset = $p + $l1;
$rc++;
}
return $subject;
}
?>
It works exactly like original str_ireplace() and defaults to 'utf-8' encoding. Replace with null if you like. Well, it's surely slower than built-in functions, however it's one of the fastest ways to do the trick.
06-Jun-2008 02:27
My apologies. I'm a PHP newbie and the count function on my script below didn't work right if you have more than one "keyword". I searched and spent a long time to get this to work right, so wanted to share it.
This is very easy to use by doing the following.
$text - is the text to search
$words - are the words to highlight (search text)
$the_place - is so that you can tell your users what "area" was searched.
<?php
function highlight_this($text, $words, $the_place) {
$words = trim($words);
$the_count = 0;
$wordsArray = explode(' ', $words);
foreach($wordsArray as $word) {
if(strlen(trim($word)) != 0)
//exclude these words from being replaced
$exclude_list = array("word1", "word2", "word3");
// Check if it's excluded
if ( in_array( strtolower($word), $exclude_list ) ) {
} else {
$text = str_ireplace($word, "<span class=\"highlight\">".strtoupper($word)."</span>", $text, $count);
$the_count = $count + $the_count;
}
}
//added to show how many keywords were found
echo "<br><div class=\"emphasis\">A search for <strong>" . $words. "</strong> found <strong>" . $the_count . "</strong> matches within the " . $the_place. ".</div><br>";
return $text;
}
//example of how to use
$text_to_highlight = highlight_this($text_to_highlight, $search_text, "Place you searched");
?>
05-Jun-2008 07:58
I modified a script from notes on the eregi_replace() function page. This is a highlight script that worked good for me.
$text - is the text to search
$words - are the words to highlight (search text)
$the_place - is so that you can tell your users what "area" was searched.
<?php
function highlight_this($text, $words, $the_place) {
$words = trim($words);
$wordsArray = explode(' ', $words);
foreach($wordsArray as $word) {
if(strlen(trim($word)) != 0)
$text = str_ireplace($word, "<span class=\"highlight\">".strtoupper($word)."</span>", $text, $count);
}
//added to show how many keywords were found
echo "<br><div class=\"emphasis\">A search for <strong>" . $words. "</strong> found <strong>" . $count . "</strong> matches within the " . $the_place. ".</div><br>";
//end script modification
return $text;
}
?>
15-Feb-2008 11:28
Here are some minor tweaks to-n00b-at-battleofthebits-dot-org's excellent function.
1) The token was set to an ASCII value 1 (which could be changed as was previously noted)
2) The $c++ was not needed
3) The while statement is not necessary for the final replacement
4) Note that this does not allow use of arrays for search and replace terms. That could be implemented using loops.
<?php
if(!function_exists('str_ireplace')){
function str_ireplace($search,$replace,$subject){
$token = chr(1);
$haystack = strtolower($subject);
$needle = strtolower($search);
while (($pos=strpos($haystack,$needle))!==FALSE){
$subject = substr_replace($subject,$token,$pos,strlen($search));
$haystack = substr_replace($haystack,$token,$pos,strlen($search));
}
$subject = str_replace($token,$replace,$subject);
return $subject;
}
}
?>
21-Jul-2007 06:54
Dreamhost hasn't upgraded to PHP 5.0 -- I came up with my own alternative, trying to make it run as much like str_ireplace() as possible. Adjust the switch-a-roo token if you think it may conflict with your needle in teh haystack.
## HOMEBREW str_ireplace() FOR PRE-PHP 5.0
if (!function_exists('str_ireplace') {
function str_ireplace($search,$replace,$subject) {
$token = '^[[term^]';
$haystack = strtolower($subject);
$needle = strtolower($search);
while (($pos=strpos($haystack,$needle))!==FALSE) {
$c++;
$subject = substr_replace($subject,$token,$pos,strlen($search));
$haystack = substr_replace($haystack,$token,$pos,strlen($search));
}
while (($pos=strpos($subject,$token))!==FALSE) {
$subject = substr_replace($subject,$replace,$pos,strlen($token));
}
return $subject;
}
}
12-Jun-2007 03:03
There appears to be a "bug" with this function in at least version 5.2.1.
If you attempt to use the function while replacing special characters, such as new lines, it will cause your entire scripts to fail. It resulted in my browser (Firefox 2) trying to download the file instead of parsing it.
Here is example code which will cause problems:
<?php
$sometext = "this is some text\n";
$sometext .= "that has a new line in it";
echo break_lines($sometext);
function break_lines ($text)
{
return str_ireplace("\n", "<br/>", $text);
}
?>
However, if you simply get rid of the "i" and use the normal str_replace, the page will load just fine.
I have also tried the same code on 5.2.3 and this version does NOT have the same problem, so it does appear to be an issue that was resolved with the newest builds of php.
I don't think it was a result of my personal environment, but I am running Debian-Sarge, Apache 2 and PHP 5.2.1/5.2.3.
31-Jan-2007 12:26
Yet another one str_ireplace ireplacement, this one will take arrays as $search and $replace
<?php
function make_pattern(&$pat, $key) {
$pat = '/'.preg_quote($pat, '/').'/i';
}
if(!function_exists('str_ireplace')){
function str_ireplace($search, $replace, $subject){
if(is_array($search)){
array_walk($search, 'make_pattern');
}
else{
$search = '/'.preg_quote($search, '/').'/i';
}
return preg_replace($search, $replace, $subject);
}
}
?>
05-Nov-2006 08:37
str_ireplace for php below version 5. :)
if(!function_exists('str_ireplace')) {
function str_ireplace($search,$replace,$subject) {
$search = preg_quote($search, "/");
return preg_replace("/".$search."/i", $replace, $subject); } }
02-Aug-2006 08:25
<?php
if(!function_exists('str_ireplace')) {
function str_ireplace($search, $replacement, $string){
$delimiters = array(1,2,3,4,5,6,7,8,14,15,16,17,18,19,20,21,22,23,24,25,
26,27,28,29,30,31,33,247,215,191,190,189,188,187,186,
185,184,183,182,180,177,176,175,174,173,172,171,169,
168,167,166,165,164,163,162,161,157,155,153,152,151,
150,149,148,147,146,145,144,143,141,139,137,136,135,
134,133,132,130,129,128,127,126,125,124,123,96,95,94,
63,62,61,60,59,58,47,46,45,44,38,37,36,35,34);
foreach ($delimiters as $d) {
if (strpos($string, chr($d))===false){
$delimiter = chr($d);
break;
}
}
if (!empty($delimiter)) {
return preg_replace($delimiter.quotemeta($search).$delimiter.'i', $replacement, $string);
}
else {
trigger_error('Homemade str_ireplace could not find a proper delimiter.', E_USER_ERROR);
}
}
}
?>
04-Jul-2005 09:07
Note that character case is being defined by your server's locale setting, which effects strings containing non-ASCII characters.
See strtolower() - http://www.php.net/strtolower and comments - internally str_ireplace converts $search and $replace to lowercase to find matches.
05-Apr-2005 08:14
here's a neat little function I whipped up to do HTML color coding of SQL strings.
<?php
/**
* Output the HTML debugging string in color coded glory for a sql query
* This is very nice for being able to see many SQL queries
* @access public
* @return void. prints HTML color coded string of the input $query.
* @param string $query The SQL query to be executed.
* @author Daevid Vincent [daevid@LockdownNetworks.com]
* @version 1.0
* @date 04/05/05
* @todo highlight SQL functions.
*/
function SQL_DEBUG( $query )
{
if( $query == '' ) return 0;
global $SQL_INT;
if( !isset($SQL_INT) ) $SQL_INT = 0;
//[dv] this has to come first or you will have goofy results later.
$query = preg_replace("/['\"]([^'\"]*)['\"]/i", "'<FONT COLOR='#FF6600'>$1</FONT>'", $query, -1);
$query = str_ireplace(
array (
'*',
'SELECT ',
'UPDATE ',
'DELETE ',
'INSERT ',
'INTO',
'VALUES',
'FROM',
'LEFT',
'JOIN',
'WHERE',
'LIMIT',
'ORDER BY',
'AND',
'OR ', //[dv] note the space. otherwise you match to 'COLOR' ;-)
'DESC',
'ASC',
'ON '
),
array (
"<FONT COLOR='#FF6600'><B>*</B></FONT>",
"<FONT COLOR='#00AA00'><B>SELECT</B> </FONT>",
"<FONT COLOR='#00AA00'><B>UPDATE</B> </FONT>",
"<FONT COLOR='#00AA00'><B>DELETE</B> </FONT>",
"<FONT COLOR='#00AA00'><B>INSERT</B> </FONT>",
"<FONT COLOR='#00AA00'><B>INTO</B></FONT>",
"<FONT COLOR='#00AA00'><B>VALUES</B></FONT>",
"<FONT COLOR='#00AA00'><B>FROM</B></FONT>",
"<FONT COLOR='#00CC00'><B>LEFT</B></FONT>",
"<FONT COLOR='#00CC00'><B>JOIN</B></FONT>",
"<FONT COLOR='#00AA00'><B>WHERE</B></FONT>",
"<FONT COLOR='#AA0000'><B>LIMIT</B></FONT>",
"<FONT COLOR='#00AA00'><B>ORDER BY</B></FONT>",
"<FONT COLOR='#0000AA'><B>AND</B></FONT>",
"<FONT COLOR='#0000AA'><B>OR</B> </FONT>",
"<FONT COLOR='#0000AA'><B>DESC</B></FONT>",
"<FONT COLOR='#0000AA'><B>ASC</B></FONT>",
"<FONT COLOR='#00DD00'><B>ON</B> </FONT>"
),
$query
);
echo "<FONT COLOR='#0000FF'><B>SQL[".$SQL_INT."]:</B> ".$query."<FONT COLOR='#FF0000'>;</FONT></FONT><BR>\n";
$SQL_INT++;
} //SQL_DEBUG
?>
21-Aug-2004 07:58
If you want to do string highlighting, for example highlighting search terms, try str_highlight().
http://aidanlister.com/repos/v/function.str_highlight.php
30-May-2004 05:36
This functionality is now implemented in the PEAR package PHP_Compat.
More information about using this function without upgrading your version of PHP can be found on the below link:
http://pear.php.net/package/PHP_Compat
