The search engine I'm using is a MySQL/PHP search engine.
I have been searching the forums for some time to try to get a solution for this problem.
If I have keywords for 3 separate images labeled:
#1 pure black
#2 pure white
#3 pure green
If I type "pure white" in the search box all 3 images come up because they all share the word "pure".
Is there a workaround or code I can add to only match exact search phrases when using multiple search keywords?
This is the code:
<?php
//get data
$button = $_GET['submit'];
$search = $_GET['search'];
$s = $_GET['s'];
if (!$s)
$s = 0;
$e = 10;
$next = $s + $e;
$prev = $s - $e;
if (strlen($search) <= 2)
echo "Must be greater then 3 chars";
else {
echo "<br /><table><tr><td><img src='juzzy.jpg' /></td><td><form action='search.php' method='GET'><input type='text' onclick=value='' size='50' name='search' value='$search'> <input type='submit' name='submit' value='Search'></form></td></tr></table>";
//connect to database
mysql_connect("","","");
mysql_select_db("");
//explode out search term
$search_exploded = explode(" ",$search);
foreach($search_exploded as $search_each) {
//construct query
$x++;
if ($x == 1)
$construct .= "keywords LIKE '%$search_each%'";
else
$construct .= " OR keywords LIKE '%$search_each%'";
}
//echo outconstruct
$constructx = "SELECT * FROM searchengine WHERE $construct";
$construct = "SELECT * FROM searchengine WHERE $construct ORDER BY keywords LIMIT $s,$e ";
$run = mysql_query($constructx);
$foundnum = mysql_num_rows($run);
$run_two = mysql_query("$construct");
if ($foundnum == 0)
echo "No results found for <b>$search</b>";
else {
echo "<table bgcolor='#0000FF' width='100%' height='1px'><br /></table><table bgcolor='#f0f7f9' width='100%' height='10px'><tr><td><div align='right'>Showing 1-10 of <b>$foundnum</b> results found for <b>$search.</b></div></td></tr></table><p>";
while ($runrows = mysql_fetch_assoc($run_two)) {
//get data
$title = $runrows['title'];
$desc = $runrows['description'];
$url = $runrows['url'];
echo "<table width='300px'>
<h4><a href='http://$url'><b>$title</b></a><br />
$desc<br>
<font color='00CC00'>$url</font></table></h4>";
}
?>
<table width='100%'>
<tr>
<td>
<div align="center">
<?php
if (!$s<=0)
echo "<a href='search.php?search=$search&s=$prev'>Prev</a>";
$i =1;
for ($x=0;$x<$foundnum;$x=$x+$e) {
echo " <a href='search.php?search=$search&s=$x'>$i</a> ";
$i++;
}
if ($s<$foundnum-$e)
echo "<a href='search.php?search=$search&s=$next'>Next</a>";
}
}
?>
</div>
</td>
</tr>
</table>
Don't explode your search string. This will force it to use the full search string as a search, rather than any one of the pieces.
Or, you could change your operator OR in your construct to AND, and that way it would require all the words to appear, regardless of order, however.
Don't use fuzzy LIKE %% queries, query by keywords = '$search'.
Related
Below is my query to show user comments. It works well:
enter
$query='SELECT
customers.cust_id,
customers.f_name,
customers.l_name,
user_comments.comment_txt,
clubs.name_club
from
customers
inner join
user_comments
on customers.cust_id = user_comments.cust_id
inner join
clubs
on user_comments.cust_id = clubs.cust_id
ORDER BY RAND() LIMIT 1,1
';
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
$nameclub =$row['name_club'];
$comment =$row['comment_txt'];
echo '<div><img src="images/arrow.gif"> Name : '.$nameclub.'</div>';
echo '<div>'.$comment.'</div><br>';
echo '<div>'.$row['f_name'].' '.$row['l_name'].'</div>';
}
echo '<p style="text-align: left"> Show all comments</ ></p> '; ?>
I now want to show just about 100 characters of a user comment. So I changed my query accordingly, but it does not work:
enter $query='SELECT
customers.cust_id,
customers.f_name,
customers.l_name,
user_comments.comment_txt.substr(comment_txt,1,100) as comment_txt,
clubs.name_club
from
customers
inner join
user_comments
on customers.cust_id = user_comments.cust_id
inner join
clubs
on user_comments.cust_id = clubs.cust_id
ORDER BY RAND() LIMIT 1,1
';
$result = mysql_query($query);
while($row = mysql_fetch_array($result)){
$nameclub =$row['name_club'];
$comment =$row['comment_txt'];
echo '<div><img src="images/arrow.gif"> Name : '.$nameclub.'</div>';
echo '<div>'.$comment.'</div><br>';
echo '<div>'.$row['f_name'].' '.$row['l_name'].'</div>';
}
echo '<p style="text-align: left"> Show all comments</ ></p> '; ?>
How can I fix my query to just get 100 characters of a comment?
You're using SUBSTR() incorrectly. Replace this:
user_comments.comment_txt.substr(comment_txt,1,100) as comment_txt,
With this:
SUBSTR(user_comments.comment_txt,1,100) as comment_txt,
Edit per comment: to add ... if the text continues past 100 characters, use
CONCAT(SUBSTR(user_comments.comment_txt,1,100), IF(LEN(user_comments.comment_txt) > 100, '...', '')) as comment_txt,
Try this
Replace this
user_comments.comment_txt.substr(comment_txt,1,100) as comment_txt,
To
SUBSTRING(user_comments.comment_txt,1,100) as comment_txt,
Mysql function_substring
Another solution is to use a php function that cuts a string into a number of words:
<?php
function cut_string($string_to_cut, $number_words, $append = "...") {
$string = array();
$string_return = "";
$return_string = "";
$string = explode(" ", $string_to_cut);
if(count($string) < $number_words) {
for($x=0; $x < count($string); $x++) {
$string_return .= $string[$x] . " ";
}
$return_string = substr($string_return, 0, -1);
}
else {
for($x=0; $x < $number_words; $x++) {
$string_return .= $string[$x] . " ";
}
$string = substr($string_return, 0, -1);
$return_string = $string . $append;
}
return($return_string);
}
?>
Note: This is word count based, not character count based.
I have concatenated three tables to one table that is edit all. Now i'm going to retrieve the all the 4 values that starts with the particular letter, But is displaying all values with starts with different letter.
include "config.php";
$term = strip_tags(substr($_POST['searchit'],0,100));
$term = mysql_real_escape_string($term);
if($term=="")
echo "Enter Something to search";
else{
$query = mysql_query("select distinct videoname,category,name,email from edit_all
where videoname like '$term%' or category like '$term%' or name like '$term%' or email like '$term%'limit 1") or die(mysql_error());
$string= '';
if (mysql_num_rows($query))
{
while($row = mysql_fetch_assoc($query)){
$string .= "<b><a href='#'>".$row['videoname']."</a></b> -<br> ";
$string .= $row['category']."-<br>";
$string .= $row['name']."-<br>";
$string .= $row['email']."-<br>";
$string .= "\n";
}
}
else{
$string = "No matches found!";
}
echo $string;
}
?>
I have two files, one is page that shows the latest additions to my site, the other is a link to the first page.
problem: if i include a like keyword instead of = in the sql, the query works. however, when i use = (which is what i want), it returns zero rows.
code snippets:
front-page.php
echo "On " . max($last_date) . ", we had <a href='/latest-txt.php?date=$md'>" . count($last_posts) . "</a> text posts!"
latest-text.php
$query = $_GET[$md];
$stmt = $db->prepare("SELECT * FROM $db_tb_name WHERE $db_tb_atr_name5 = ? ORDER BY RAND () LIMIT 0, 15");
if($stmt->execute(array("%$query%"))){
echo "Search Results<ol>";
while($data_fetch = $stmt->fetch(PDO::FETCH_ASSOC)){
echo "<li>";
echo "<div class='tagtext'>AUTHOR: ";
echo substr($data_fetch[$db_tb_atr_name2], 0,160)," "," ";
echo "TAG: ";
echo substr($data_fetch[$db_tb_atr_name3], 0,160)," ";
//echo substr($data_fetch[$db_tb_atr_name4], 0,160)," ";
echo "</div>";
echo "<div class='tagtext'>MESSAGE: ";
echo substr($data_fetch[$db_tb_atr_name], 0,160);
echo "</div>";
//echo substr($data_fetch[$db_tb_atr_name], 0,160);
echo "</li><hr/>";
}
}
echo "</ol>";
can anybody help? thanks.
Because you are trying use % as wilcard in your search criteria without LIKE which means concatenating % character to $query value.
You are querying
SELECT * FROM $db_tb_name WHERE $db_tb_atr_name5 = '%2013-09-30%' ORDER BY RAND () LIMIT 0, 15
because of there is no row which has a value '%2013-09-30%' in your table the query returns zero rows.
You should change $stmt->execute(array("%$query%")) to $stmt->execute(array($query)) before removing like.
I suggest you to change your way binding parameter.
write
$stmt->bindValue(1, $query, PDO::PARAM_STR);
before executing and execute
if($stmt->execute())
{
...
}
In addition to this we have to know what value $query and $md have.
So take a try with $_GET['date'].
Another approach is to understand what is wrong:
1. If you get 0 rows with no error message, your query works fine.
2. If you get 0 rows without knowing you have an exception let's make a little modification on your code:
try
{
$query = $_GET[$md];
$stmt = $db->prepare("SELECT * FROM $db_tb_name WHERE $db_tb_atr_name5 = ? ORDER BY RAND () LIMIT 0, 15");
$stmt->bindValue(1, $query, PDO::PARAM_STR);
$stmt->execute();
{
echo "Search Results<ol>";
while($data_fetch = $stmt->fetch(PDO::FETCH_ASSOC))
{
echo "<li>";
echo "<div class='tagtext'>AUTHOR: ";
echo substr($data_fetch[$db_tb_atr_name2], 0,160)," "," ";
echo "TAG: ";
echo substr($data_fetch[$db_tb_atr_name3], 0,160)," ";
echo "</div>";
echo "<div class='tagtext'>MESSAGE: ";
echo substr($data_fetch[$db_tb_atr_name], 0,160);
echo "</div>";
echo "</li><hr/>";
}
}
echo "</ol>";
}
catch (PDOException $pdoe)
{
throw $pdoe;
}
replace $query=$_GET[$md] with $query=$_GET['date']
replace "%$query%" with $query
(both as suggested by some of you :) )
It is due to the % wildcard within your execute array, the Equal Operator = is a comparison operator and takes % as a literal character.
LIKE is pattern matching that can use wildcards. MySQL 5.7: String Comparison Functions
% Matches any number of characters, even zero characters
_ Matches exactly one character
I have the following PHP search script.
When I search for 1234567, it matches the exact phrase but I want it to match only initial 4 characters i.e. 1234.
Explanation:
I want it to count the initial 4 characters and display the result matching those initial characters. E.g. if someone search for 1234567 then the script should count the initial 4 characters i.e. 1234 and show the results. Similarly if someone search 456789 then the script should count the initial 4 characters i.e. 4567 and show the results.
///explode search term
$search_exploded = explode(" ",$search);
foreach($search_exploded as $search_each)
{
//construct query
$x++;
if ($x==1)
$construct .= "keywords LIKE '%$search_each%'";
else
$construct .= " OR keywords LIKE '%$search_each%'";
}
//echo out construct
$construct = "SELECT * FROM numbers WHERE $construct";
$run = mysql_query($construct);
$foundnum = mysql_num_rows($run);
if ($foundnum==0)
echo "No results found.";
{
echo "$foundnum results found.<p><hr size='1'>";
while ($runrows = mysql_fetch_assoc($run))
{
//get data
$title = $runrows['title'];
$desc = $runrows['description'];
$url = $runrows['url'];
echo "<b>$title</b>
<b>$desc</b>
<a href='$url'>$url</a><p>";
You can replace your foreach with:
foreach($search_exploded as $search_each)
{
$str = mysql_real_escape_string(substr($search_each, 0, 4));
//construct query
$x++;
if ($x==1) $construct .= "keywords LIKE '$str%'";
else $construct .= " OR keywords LIKE '$str%'";
}
To modify your existing code to only use the first 4 words, you just need to change your loop a bit:
Change this-
foreach($search_exploded as $search_each) {
To this -
for($i = 0; $i < min(count($search_exploded), 4); ++$i) {
$search_each = $search_exploded[$i];
Add the following code to the top of your foreach loop:
if(strlen($search_each) > 4) $search_each = substr($search_each, 0, 4);
Like this:
$search_exploded = explode(" ", $search);
foreach($search_exploded as $search_each)
{
if(strlen($search_each) > 4) $search_each = substr($search_each, 0, 4);
// your code
}
This code will search for first 4 characters in every word if that word is longer than 4.
I'm trying to put an image as a separator between menu items but not on the outside and I'm not sure how to do this.. So it would end up being something like this:
HOME | ABOUT | CONTACT
unfortunately my code puts one after every entry including the last one.
mysql_select_db($database_db_connection, $db_connection);
$query_rsMenu = "SELECT * FROM menu WHERE online = 1 ORDER BY position ASC";
$rsMenu = mysql_query($query_rsMenu, $db_connection) or die(mysql_error());
echo "<ul class='MenuBarVertical'>\n";
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
echo (" <li>" . $row_rsMenu['menuName'] . " <img src='SiteFiles/Site/separator.jpg' /> </li>\n");
}
echo "</ul>\n";
mysql_free_result($rsMenu);
Thanks
You could also build an array and use implode when you print it out. This also separates the database model from the view a little better.
mysql_select_db($database_db_connection, $db_connection);
$query_rsMenu = "SELECT * FROM menu WHERE online = 1 ORDER BY position ASC";
$rsMenu = mysql_query($query_rsMenu, $db_connection) or die(mysql_error());
$array = array();
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
$array[] = "<li>" . $row_rsMenu['menuName'] . "</li>\n";
}
mysql_free_result($rsMenu);
echo "<ul class='MenuBarVertical'>\n";
echo implode(' <img src="SiteFiles/Site/separator.jpg" /> ', $array);
echo "</ul>\n";
Of course the tags end up between the li instead of inside, but since you are making the li inline I think it will work.
The easy solution is to special case either the last iteration or the first one. The first one is usually easier: set $first = true outside the loop, inside the loop: if (!$first) { print 'separator'; }.
$count = 0;
$dbRows = mysql_num_rows($rsMenu);
while($row_rsMenu = mysql_fetch_assoc($rsMenu)) {
$count++;
echo (" <li><a href=\"../" . $row_rsMenu['menuURL'] . "\">" . $row_rsMenu['menuName'];
if($count < $dbRows)
echo ("</a> <img src='SiteFiles/Site/separator.jpg' /> </li>\n");
}
You could use mysql_num_rows() to get the number of rows from the result set, and build some logic against the result.
Yet another answer :
for ($i = 1; $i <= mysql_num_rows($rsMenu); $i++) {
$row_rsMenu = mysql_fetch_assoc($rsMenu);
// do something;
if ($i == mysql_num_rows($rsMenu) - 1) {
// this is the last element, do something;
}
}