FRIHOST FORUMS SEARCH FAQ TOS BLOGS COMPETITIONS
You are invited to Log in or Register a free Frihost Account!


Highlighting Search Terms





Shike
I have a Search script to search a MySQL database. I was wondering if there was a way to have the PHP highlight the search terms in the records, or if I would have to use javascript, or something of that nature?
Marston
Use the str_replace() function.
BlackSkad
Asumming you have an array of search terms and a result-string fetched from the database, you can use this code (as a clarification to Marstons 'use str_replace')

Code:
<?php
$textFromDB = "some string, fetched from the database";
$searchTerms = {"some", "fetched", "database"};
foreach ($searchTerms as $term) {
   $higlight = '<span style="background-color:yellow">'.$term.'</span>';
   $textFromDB = str_replace ($term, $highlight, $textFromDB);
}
echo $textFromDB;
?>
hexkid
Shike wrote:
I have a Search script to search a MySQL database. I was wondering if there was a way to have the PHP highlight the search terms in the records, or if I would have to use javascript, or something of that nature?


I'd use preg_replace():
Code:
<?php
$DBtxt = 'The quick brown fox jumps over the lazy dog.';
$terms = array('quick', 'over');
$pat = '/(' . implode('|', $terms) . ')/';
$highlighted_text = preg_replace($pat, '<span class="highlight">$1</span>', $DBtxt);
?>
Shike
BlackSkad wrote:
Asumming you have an array of search terms and a result-string fetched from the database, you can use this code (as a clarification to Marstons 'use str_replace')

Code:
<?php
$textFromDB = "some string, fetched from the database";
$searchTerms = {"some", "fetched", "database"};
foreach ($searchTerms as $term) {
   $higlight = '<span style="background-color:yellow">'.$term.'</span>';
   $textFromDB = str_replace ($term, $highlight, $textFromDB);
}
echo $textFromDB;
?>


First Question. Would I place this before or after (or within) my script for displaying the information.

Which would be say:

Code:
 <?php while ($newArray = mysql_fetch_array($result)) {
   $name = $newArray['name'];
   $short = $newArray['shortdec'];
   $caster = $newArray ['caster'];
   $components = $newArray ['components'];
   $school = $newArray ['school'];
   $id = $newArray ['id'];
   $source = $newArray ['source'];
   $resnum = $count++ ;
   echo "<table class='short'>
         <tr>
            <td rowspan='3' width='30'><strong><font size='+1'>$resnum)</font></strong></td><td colspan='3'><strong><a href=\"dnd.php?term=$id\" target='_self'>$name</a></strong>: $short</td>
         </tr>
         <tr>
            <td colspan='3'><em>Casting Class/ Spell Level</em>: $caster</td>
         </tr>
         <tr>
            <td width='200'><em>School</em>: $school</td><td width='200'><em>Components</em>: $components</td><td width='200'><em>Source</em>: $source</td>
         </tr></table>\n";
}?>


I would assume I would place it before the 'echo' command to display the results.

Also, I have 3 possible search fields would I do an If (){}else() setup (which is how I did the search commands) so would I do

Code:
<?php

$name =$newArray['name']; //just using the variable from above
if ($term3 != "") {
        $terms = array($terms1, $terms2, $terms3)
} elseif ($term2 != "") {
         $terms = array($terms1, $terms2)
} elseif ($term1 != "") {
         $terms = $terms1
}
foreach ($terms as $term) {
   $higlight = "<span class='term'>$term</span>";
   $name = str_replace ($term, $highlight, $name);
}
echo //echo as above?
?>


or instead of
Code:
if ($term3 != "") {
        $terms = array($terms1, $terms2, $terms3)
} elseif ($term2 != "") {
         $terms = array($terms1, $terms2)
} elseif ($term1 != "") {
         $terms = $terms1
}


Can I do
Code:
$terms = array($terms1, $terms2, $terms3)

and when $terms2 and $terms3 are empty they wouldn't add to the Array?

Also, would I do this for all of my variables, seperately, from the DB?
Shike
Could I just do this?

Code:
 <?php while ($newArray = mysql_fetch_array($result)) {
   $name = $newArray['name'];
   $short = $newArray['shortdec'];
   $caster = $newArray ['caster'];
   $components = $newArray ['components'];
   $school = $newArray ['school'];
   $id = $newArray ['id'];
   $source = $newArray ['source'];
   $resnum = $count++ ;
        if ($term3 != "") {
                $terms = array($terms1, $terms2, $terms3);
        } elseif ($term2 != "") {
                 $terms = array($terms1, $terms2);
        } elseif ($term1 != "") {
                 $terms = $terms1;
        }
        foreach ($terms as $term) {
           $higlight = "<span class='term'>$term</span>";
           $name = str_replace ($term, $highlight, $name);
           $short = str_replace ($term, $highlight, $short);
           $caster = str_replace ($term, $highlight, $caster);
           $school = str_replace ($term, $highlight, $school);
           $source = str_replace ($term, $highlight, $source);
        }
   echo "<table class='short'>
         <tr>
            <td rowspan='3' width='30'><strong><font size='+1'>$resnum)</font></strong></td><td colspan='3'><strong><a href=\"dnd.php?term=$id\" target='_self'>$name</a></strong>: $short</td>
         </tr>
         <tr>
            <td colspan='3'><em>Casting Class/ Spell Level</em>: $caster</td>
         </tr>
         <tr>
            <td width='200'><em>School</em>: $school</td><td width='200'><em>Components</em>: $components</td><td width='200'><em>Source</em>: $source</td>
         </tr></table>\n";
}?>
Shike
Shike wrote:
Could I just do this?

Code:
 <?php while ($newArray = mysql_fetch_array($result)) {
   $name = $newArray['name'];
   $short = $newArray['shortdec'];
   $caster = $newArray ['caster'];
   $components = $newArray ['components'];
   $school = $newArray ['school'];
   $id = $newArray ['id'];
   $source = $newArray ['source'];
   $resnum = $count++ ;
        if ($term3 != "") {
                $terms = array($terms1, $terms2, $terms3);
        } elseif ($term2 != "") {
                 $terms = array($terms1, $terms2);
        } elseif ($term1 != "") {
                 $terms = $terms1;
        }
        foreach ($terms as $term) {
           $higlight = "<span class='term'>$term</span>";
           $name = str_replace ($term, $highlight, $name);
           $short = str_replace ($term, $highlight, $short);
           $caster = str_replace ($term, $highlight, $caster);
           $school = str_replace ($term, $highlight, $school);
           $source = str_replace ($term, $highlight, $source);
        }
   echo "<table class='short'>
         <tr>
            <td rowspan='3' width='30'><strong><font size='+1'>$resnum)</font></strong></td><td colspan='3'><strong><a href=\"dnd.php?term=$id\" target='_self'>$name</a></strong>: $short</td>
         </tr>
         <tr>
            <td colspan='3'><em>Casting Class/ Spell Level</em>: $caster</td>
         </tr>
         <tr>
            <td width='200'><em>School</em>: $school</td><td width='200'><em>Components</em>: $components</td><td width='200'><em>Source</em>: $source</td>
         </tr></table>\n";
}?>


Ok, Doing this just removes the search terms from the text. (btw I'm using .term {font-weight: bold; font-style: italic;} as my hightlighting.)
hexkid
Shike wrote:
Could I just do this?

It appears it should work; I didn't test it.

Just one thing
Shike wrote:
Code:
        if ($term3 != "") {
                $terms = array($terms1, $terms2, $terms3);
        } elseif ($term2 != "") {
                 $terms = array($terms1, $terms2);
        } elseif ($term1 != "") {
                 $terms = $terms1;
        }

I'd make the last line also create an array
Code:
        } elseif ($term1 != "") {
                 $terms = array($terms1);
        }
Shike
hexkid wrote:
Shike wrote:
Could I just do this?

It appears it should work; I didn't test it.

Just one thing
Shike wrote:
Code:
        if ($term3 != "") {
                $terms = array($terms1, $terms2, $terms3);
        } elseif ($term2 != "") {
                 $terms = array($terms1, $terms2);
        } elseif ($term1 != "") {
                 $terms = $terms1;
        }

I'd make the last line also create an array
Code:
        } elseif ($term1 != "") {
                 $terms = array($terms1);
        }


Ok, First question. Did I place it in the right place in the code?

Second. $terms1 already is an array, but even with your change it still removed the term from the result.

Hmmm. Any other ideas?? Smile
Shike
Question will
Code:
$terms1 = explode(" ", $term1);
return an array with a single term if only one term is given in
Code:
$term1 = $_GET['term1'];
hexkid
Shike wrote:
Did I place it in the right place in the code?

Yes.

Shike wrote:
$terms1 already is an array, but even with your change it still removed the term from the result.

Well ... if $terms1 is an array, the foreach() will have arrays for its loop variable
Code:
foreach ($terms as $term) {
  // remenber $term is an array!!
  $highlight = "<span class='term'>$term</span>"; ### oops!
}

I think you want the array_merge() function.
hexkid
Shike wrote:
Question will
Code:
$terms1 = explode(" ", $term1);
return an array with a single term if only one term is given in
Code:
$term1 = $_GET['term1'];
Yes.

Code:
$terms1 = explode(" ", "abc");
$terms2 = array("abc");
if ($terms1 === $terms2) { echo '$terms1 and $terms2 are equal.'; }
Shike
That's what I thought (and hoped). Now if only I could get the highlighting to work Smile
Shike
hexkid wrote:
Shike wrote:
Did I place it in the right place in the code?

Yes.

Shike wrote:
$terms1 already is an array, but even with your change it still removed the term from the result.

Well ... if $terms1 is an array, the foreach() will have arrays for its loop variable
Code:
foreach ($terms as $term) {
  // remenber $term is an array!!
  $highlight = "<span class='term'>$term</span>"; ### oops!
}

I think you want the array_merge() function.


I figured that out after a little while Smile. Even using the array_merge() function, the code is still removing the terms from the record. hmmm.
hexkid
Shike wrote:
the code is still removing the terms from the record. hmmm.


This works Smile
Code:
<?php
$txt = 'two is "dois" in portuguese and "deux" in french; five is "cinco" and "cinq" respectively.';

echo $txt, '<br><hr><br>';

$terms1 = array('two', 'five');
$terms2 = array('dois', 'cinco');
// $terms3 = array('deux', 'cinq');

if (!empty($terms3)) {
  $terms = array_merge($terms1, $terms2, $terms3);
} else if (!empty($terms2)) {
  $terms = array_merge($terms1, $terms2);
} else {
  $terms = $terms1;
}

foreach ($terms as $term) {
  $highlight = '<span style="background-color: yellow">' . $term . '</span>';
  $txt = str_replace($term, $highlight, $txt);
}
echo $txt;
?>
Shike
hexkid wrote:

Code:

  $highlight = "<span class='term'>$term</span>"; ### oops!
}


Why is this an oops. It works for everything else I have in the code. Also, when I do it this way.
Code:
$highlight = '<span class="term">' . $term . '</span>';


it still just removes the text.
hexkid
Shike wrote:
hexkid wrote:

Code:

  $highlight = "<span class='term'>$term</span>"; ### oops!
}


Why is this an oops. It works for everything else I have in the code. Also, when I do it this way.
Code:
$highlight = '<span class="term">' . $term . '</span>';


it still just removes the text.


If, as you say, $term is an array $highlight will become "<span class='term'>Array</span>"
Shike
hexkid wrote:
Shike wrote:
hexkid wrote:

Code:

  $highlight = "<span class='term'>$term</span>"; ### oops!
}


Why is this an oops. It works for everything else I have in the code. Also, when I do it this way.
Code:
$highlight = '<span class="term">' . $term . '</span>';


it still just removes the text.


If, as you say, $term is an array $highlight will become "<span class='term'>Array</span>"


But it is still removes the terms I actually searched for.

Should I post my entire Script (a link to a txt file) so we can work through it?
hexkid
Shike wrote:
Should I post my entire Script (a link to a txt file) so we can work through it?


Do that, or use Pastebin.

I'll try to make it work.
I think I will follow this procedure (you can try that yourself):
1. reformat Smile
edit 1.5. comment out most HTML stuff
2. remove all database functions and substitute with "appropriate" replacements
3. test the script
4. remove the multiple terms stuff ($terms2 and $terms3)
5. test the script
6. add the multiple terms stuff
7. add the database functions
edit 7.5. uncomment the HTML stuff
Shike
Hexkid: Thanks for all your help. Here is the Full Script. I have
Code:
    /*if (!empty($terms3)) {
                $terms = array_merge($terms1, $terms2, $terms3);
        } elseif (!emtpy($terms2)) {
                 $terms = array_merge($terms1, $terms2);
        } else {
                  $terms = $terms1;
        }
        foreach ($terms as $term) {
           $higlight = "<span class='term'>$term</span>";
           $name = str_replace ($term, $highlight, $name);
           $short = str_replace ($term, $highlight, $short);
           $caster = str_replace ($term, $highlight, $caster);
           $school = str_replace ($term, $highlight, $school);
           $source = str_replace ($term, $highlight, $source);
        }*/
in a multiline note (so that the code skips over it for current usability) to use the code as is go to the search page.

Again, thanks for your help. Smile
hexkid
Your script with my edits is here.

The most important thing to solve problems is at the very top of it

error_reporting(E_ALL);
ini_set('display_errors', '1');




Search for "hexkid" within the script to see what I did Smile


Can't stress this enough:

The most important thing to solve problems is

error_reporting(E_ALL);
ini_set('display_errors', '1');
Shike
Thanks Hexkid, It works Great.
Shike
Last question about highlighting. Is there a way I can make the hightlighting NOT case sensitive?
hexkid
Shike wrote:
Last question about highlighting. Is there a way I can make the hightlighting NOT case sensitive?


You can try str_ireplace() or, my preferred way, (which I also wrote about way up there) preg_replace().

Code:
<?php
header('Content-Type: text/plain');
$txt = 'This is a large description to Test searching functions.';

$txt2 = str_ireplace('test', '*test*', $txt);
$txt3 = preg_replace('/(test)/i', '*\1*', $txt);

echo "$txt\n$txt2\n$txt3";
?>


str_ireplace() will not respect the original case.
preg_replace(), with backreferences, will respect the original case.


Edit: you may want to replace your code block with
Code:
        foreach ($terms as $term) {
           ### hexkid: higlight had a typo
           $srch = '/(' . $term . ')/i';
           $highlight = "<span class='term'>\\1</span>";
           $name = preg_replace ($srch, $highlight, $name);
           $short = preg_replace ($srch, $highlight, $short);
           $caster = preg_replace ($srch, $highlight, $caster);
           $school = preg_replace ($srch, $highlight, $school);
           $source = preg_replace ($srch, $highlight, $source);
        }
Shike
hexkid wrote:
Shike wrote:
I have a Search script to search a MySQL database. I was wondering if there was a way to have the PHP highlight the search terms in the records, or if I would have to use javascript, or something of that nature?


I'd use preg_replace():
Code:
<?php
$DBtxt = 'The quick brown fox jumps over the lazy dog.';
$terms = array('quick', 'over');
$pat = '/(' . implode('|', $terms) . ')/';
$highlighted_text = preg_replace($pat, '<span class="highlight">$1</span>', $DBtxt);
?>



What is the variable $1 defined as?

(using
Code:
    if ( $terms3 != "" ) {
                $terms = array_merge($terms1, $terms2, $terms3);
        } elseif ( $terms2 != "" ) {
                 $terms = array_merge($terms1, $terms2);
        } else {
                  $terms = $terms1;
        }
$pat = '/(' . implode('|', $terms) . ')/';
$name = preg_replace($pat, "<span class='term'>$1</span>", $name);
$short = preg_replace($pat, "<span class='term'>$1</span>", $short);
$caster = preg_replace($pat, "<span class='term'>$1</span>", $caster);
$school = preg_replace($pat, "<span class='term'>$1</span>", $school);
$source = preg_replace($pat, "<span class='term'>$1</span>", $source);
I still only get case sensitive highlighting)
hexkid
Shike wrote:
hexkid wrote:
Code:
<?php
$DBtxt = 'The quick brown fox jumps over the lazy dog.';
$terms = array('quick', 'over');
$pat = '/(' . implode('|', $terms) . ')/';
$highlighted_text = preg_replace($pat, '<span class="highlight">$1</span>', $DBtxt);
?>


What is the variable $1 defined as?

That's a back reference Smile

Shike wrote:
using
Code:
    if ( $terms3 != "" ) {
                $terms = array_merge($terms1, $terms2, $terms3);
        } elseif ( $terms2 != "" ) {
                 $terms = array_merge($terms1, $terms2);
        } else {
                  $terms = $terms1;
        }
$pat = '/(' . implode('|', $terms) . ')/';
$name = preg_replace($pat, "<span class='term'>$1</span>", $name);
$short = preg_replace($pat, "<span class='term'>$1</span>", $short);
$caster = preg_replace($pat, "<span class='term'>$1</span>", $caster);
$school = preg_replace($pat, "<span class='term'>$1</span>", $school);
$source = preg_replace($pat, "<span class='term'>$1</span>", $source);
I still only get case sensitive highlighting)

Well, the case sensitivity wasn't an issue back then, when I wrote that post. You need to change the regular expression just a little bit. Try adding an "i" to the end of it:
Code:
$pat = '/(' . implode('|', $terms) . ')/i';
Shike
hexkid wrote:

Shike wrote:
using
Code:
    if ( $terms3 != "" ) {
                $terms = array_merge($terms1, $terms2, $terms3);
        } elseif ( $terms2 != "" ) {
                 $terms = array_merge($terms1, $terms2);
        } else {
                  $terms = $terms1;
        }
$pat = '/(' . implode('|', $terms) . ')/';
$name = preg_replace($pat, "<span class='term'>$1</span>", $name);
$short = preg_replace($pat, "<span class='term'>$1</span>", $short);
$caster = preg_replace($pat, "<span class='term'>$1</span>", $caster);
$school = preg_replace($pat, "<span class='term'>$1</span>", $school);
$source = preg_replace($pat, "<span class='term'>$1</span>", $source);
I still only get case sensitive highlighting)

Well, the case sensitivity wasn't an issue back then, when I wrote that post. You need to change the regular expression just a little bit. Try adding an "i" to the end of it:
Code:
$pat = '/(' . implode('|', $terms) . ')/i';


Hmm, it is still case sensitive. Smile BTW, I do appreciate your help.
hexkid
Shike wrote:
Hmm, it is still case sensitive.

It works for me. My version (no database) is available right next to the updated source.

I made two screen shots, one with lowercase inputs and the other with upper case inputs (the screen shots will be deleted from the server they're on in a month).
Shike
Ok, here's the behavior I'm getting with 1 Term or search box used and 2 terms or search boxes used.
Shike
Hey, this
Code:
      $pat = '/(' . implode('|', $terms) . ')/i';
      $name = preg_replace($pat, "<span class='term'>$1</span>", $name);
      $short = preg_replace($pat, "<span class='term'>$1</span>", $short);
      $caster = preg_replace($pat, "<span class='term'>$1</span>", $caster);
      $school = preg_replace($pat, "<span class='term'>$1</span>", $school);
      $source = preg_replace($pat, "<span class='term'>$1</span>", $source);
works. (I've been keeping all versions of the code in my script as notes until I found one that worked. Smile )

Again thanks for all your help.
Shike
Ok, one more question.

Why would the preg_replace() function force html tages not to parse? I use the str_replace() it parses just fine, but I use the preg_replace() and it doesn't work.

is there a way that I can use "<" and ">" as some sort of stop character so that it skips over anything within the tags?

Any suggestions?
hexkid
Shike wrote:
Hey, this
Code:
// ...
works. (I've been keeping all versions of the code in my script as notes until I found one that worked. Smile )

Again thanks for all your help.

After all $terms is an array!
Glad you have it working Smile
Related topics
Does anyone know how to get your site to appear higher ?
Linking from a high page rank site
Free SEO: Quality Websites Only Please
Google's Secret Revealed
Google News Offers RSS and Atom Feeds
One domain pointing to multiple accounts?..
SEO & Website marketing how do you get clicks? Or do yo
Hello from Boston
Intra site search...
phpBB 2.0.21 Released
I found a googlebot searching my forum...
Getting inbound search engine links
Google Insight for Search Finding trends in specific region
Search Bots How?
Reply to topic    Frihost Forum Index -> Scripting -> Php and MySQL

FRIHOST HOME | FAQ | TOS | ABOUT US | CONTACT US | SITE MAP
© 2005-2011 Frihost, forums powered by phpBB.