Multi word search in PHP/MySQL - php

I'm struggling to create a search that searches for multiple words. My first attempt yielded no results whatsoever and is as follows:
require_once('database_conn.php');
if($_POST){
$explodedSearch = explode (" ", $_POST['quickSearch']);
foreach($explodedSearch as $search){
$query = "SELECT *
FROM jobseeker
WHERE forename like '%$search%' or surname like '%$search%'
ORDER BY userID
LIMIT 5";
$result = mysql_query($query);
}
while($userData=mysql_fetch_array($result)){
$forename=$userData['forename'];
$surname=$userData['surname'];
$profPic=$userData['profilePicture'];
$location=$userData['location'];
echo "<div class=\"result\">
<img class=\"quickImage\" src=\"" . $profPic. "\" width=\"45\" height=\"45\"/>
<p class=\"quickName\">" . $forename . " " . $surname . "</p>
<p class=\"quickLocation\"> " . $location . "</p>
</div>";
}
}
I also tried the following, which yielded results, but as you can imagine, I was getting duplicate results for every word I entered:
if($_POST){
$explodedSearch = explode (" ", $_POST['quickSearch']);
foreach($explodedSearch as $search){
$query = "SELECT *
FROM jobseeker
WHERE forename like '%$search%' or surname like '%$search%'
ORDER BY userID
LIMIT 5";
$result .= mysql_query($query);
while($userData=mysql_fetch_array($result)){
$forename=$userData['forename'];
$surname=$userData['surname'];
$profPic=$userData['profilePicture'];
$location=$userData['location'];
echo "<div class=\"result\">
<img class=\"quickImage\" src=\"" . $profPic. "\" width=\"45\" height=\"45\"/>
<p class=\"quickName\">" . $forename . " " . $surname . "</p>
<p class=\"quickLocation\"> " . $location . "</p>
</div>";
}
}
}
I'm pretty much at a loss as to how to proceed with this, any help would be greatly appreciated.
EDIT:
if($_POST){
$quickSearch = $_POST['quickSearch'];
$explodedSearch = explode (" ", trim($quickSearch));
$queryArray = array();
foreach($explodedSearch as $search){
$term = mysql_real_escape_string($search);
$queryArray[] = "forename like '%" . $term . "%' surname like '%" . $term . "%'";
}
$implodedSearch = implode(' or ', $queryArray);
$query="SELECT *
FROM jobseeker
WHERE ($implodedSearch)
ORDER BY userID
LIMIT 5";
$result = mysql_query($query);
while($userData=mysql_fetch_array($result, MYSQL_ASSOC)){
$forename=$userData['forename'];
$surname=$userData['surname'];
$profPic=$userData['profilePicture'];
$location=$userData['location'];
echo "<div class=\"result\">
<img class=\"quickImage\" src=\"" . $profPic. "\" width=\"45\" height=\"45\"/>
<p class=\"quickName\">" . $forename . " " . $surname . "</p>
<p class=\"quickLocation\"> " . $location . "</p>
</div>";
}
}

I've been working on the same subject (search with keywords) for a while and this how i did it :
$words = $_POST['keywords'];
if(empty($words)){
//redirect somewhere else!
}
$parts = explode(" ",trim($words));
$clauses=array();
foreach ($parts as $part){
//function_description in my case , replace it with whatever u want in ur table
$clauses[]="function_description LIKE '%" . mysql_real_escape_string($part) . "%'";
}
$clause=implode(' OR ' ,$clauses);
//select your condition and add "AND ($clauses)" .
$sql="SELECT *
FROM functions
WHERE
user_name='{$user_name}'
AND ($clause) ";
$results=mysql_query($sql,$connection);
if(!$results){
redirect("errors/error_db.html");
}
else if($results){
$rows = array();
<?php
while($rows = mysql_fetch_array($results, MYSQL_ASSOC))
{
// echo whatever u want !
}
?>
-- Now this is how it look when i tried to run it with FULLTEXT search :
But you should set the table type as "MyISAM"
<?php
$words = mysql_real_escape_string($_POST['function_keywords']);
if(empty($words)){
redirect("welcome.php?error=search_empty");
}
//if the columns(results)>1/2(columns) => it will return nothing!(use "NATURAL LANGUAGE"="BOOLEAN")
$sql="SELECT * FROM functions
WHERE MATCH (function_description)
AGAINST ('{$words}' IN NATURAL LANGUAGE MODE)";
$results=mysql_query($sql,$connection);
if(!$results){
redirect("errors/error_db.html");
}
else if($results){
$rows = array();
while($rows = mysql_fetch_array($results, MYSQL_ASSOC))
{
// echo
}
}
?>

Perhaps what you are looking for is a MySQL full-text search.
For your example, you could do something like:
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$search = $_POST['quickSearch'];
// Todo: escape $search
$sql = "
SELECT
*,
MATCH (`forename`)
AGAINST ('{$search}' IN NATURAL LANGUAGE MODE) AS `score`
FROM `jobseeker`
WHERE
MATCH (`forename`)
AGAINST ('{$search}' IN NATURAL LANGUAGE MODE)";
// Todo: execute query and gather results
}
Note that you will need to add a FULLTEXT index to the column forename.

Take a look at MySQL fulltext searches, if you must use MySQL. Otherwise take a look at SOLR, which is a fulltext search engine. You can use MySQL and SOLR in combination to provide enterprise level search capabilities for your apps.

here's what i did
if (isset($_POST['search'])){
$words = mysql_real_escape_string($_POST['searchfield']);
$arraySearch = explode(" ", trim($words));
$countSearch = count($arraySearch);
$a = 0;
$query = "SELECT * FROM parts WHERE ";
$quote = "'";
while ($a < $countSearch)
{
$query = $query."description LIKE $quote%$arraySearch[$a]%$quote ";
$a++;
if ($a < $countSearch)
{
$query = $query." AND ";
}
}
$result=mysql_query($query) or die(error);
//you could just leave it here, short and sweet but i added some extra code for if it doesnt turn up any results then it searches for either word rather than boths words//
$num = mysql_num_rows($result);
if ($num == 0){
$a = 0;
$query = "SELECT * FROM parts WHERE ";
while ($a < $countSearch)
{
$query = $query."description LIKE $quote%$arraySearch[$a]%$quote ";
$a++;
if ($a < $countSearch)
{
$query = $query." OR ";
$msg = "No exact match for: $words. Maybe this is what you're looking for though? If not please try again.";
}
}
}
$result=mysql_query($query) or die($query);
if (mysql_num_rows($result) == 0){
$msg = "No results, please try another search";
}
}

Related

How to implement REGEXP in foreach the right way?

Hello,
How to add regexp the right way in this code in order to search for exact word in database?
$condition = '';
$name = "he is mad";
$query = explode(" ", $name);
foreach($query as $text) {
$condition .= "test LIKE '%".mysqli_real_escape_string($conn, $text)."%' OR ";
}
$condition = rtrim($condition, " OR ");
$sql_query = "SELECT * FROM test WHERE " . $condition;
$result = mysqli_query($conn, $sql_query);
if ($result->num_rows > 0) {
echo "1";
} else {
echo "0";
}
$conn->close();
I want to add this to the php code
SELECT
*
FROM
`table`
WHERE
Description regexp '(^|[[:space:]])pen([[:space:]]|$)';
It only works with me like this without foreach:
$sql_query = "SELECT * FROM test WHERE test regexp '(^|[[:space:]])$condition([[:space:]]|$)'";
You just need to remove the last " OR " from your $condition
<?php
$condition = '';
$name = "Hello world i am so sad";
$query = explode(" ", $name);
foreach($query as $text) {
$condition .= "test LIKE '%".mysqli_real_escape_string($conn, $text)."%' OR ";
}
// HERE REMOVE LAST " OR " FROM STRING
$condition = rtrim($condition, " OR ");
$sql_query = "SELECT * FROM test WHERE " . $condition;
$result = mysqli_query($conn, $sql_query);
if ($result->num_rows > 0) {
echo "1";
} else {
echo "0";
}
$conn->close();
If you have a phrase that is separated by spaces and you want to see if there is any overlap with the words, you can possibly use regular expressions:
where col regexp replace($name, ' ', '|')
Note that you should be passing $name in as a parameter.
If you care about word boundaries, you can introduce them into the regular expression. However, the exact form may depend on which regular expression library MySQL is using. The idea is:
where col regexp concat('\\b', replace($name, ' ', '\\b|\\b'), '\\b')

How can I make a php tag search field with AND and OR conditions?

I am trying to create a search field where people can search with tags that are saved in our database (ajax). The problem is that I want the user to be able to search with tags for content, where the content MUST have tags attached that include all the tags that were used for the search. So let's say I search for 'bwm red', I want to only show content with both the tags 'bmw' and 'red' attached to it. So NO content with only one of the two tags.
Additionally, the user can search for tags that are optional, so let's say the user searches for 'red yellow', the results should be content either with tags 'red' or 'yellow', where it also matches with the MUST search field. By doing so you get a very specific search.
In the photo here I have included the design how the search field should work, and it should be more clear what I am trying to create.
I have also written some code, but as you can see it is not working how I want to be.
Any idea how I can solve this problem?
<form action="search.php" method="post" >
  <h2>Search Keywords:</h2>
<h3>MUST</h3>
    <input type="text" name="must">
    <h3>Optional</h3>
<input type="text" name="keyword">
    <input type="submit" value="Search">
</form>
if(!empty($_POST))
{
$aMust = explode(" ", $_POST['must']);
$aKeyword = explode(" ", $_POST['keyword']);
$query ="SELECT * FROM table1 WHERE field1 like '%" . $aKeyword[0] . "%'";
for($i = 1; $i < count($aKeyword); $i++) {
if(!empty($aKeyword[$i])) {
$query .= " OR field1 like '%" . $aKeyword[$i] . "%'";
}
}
$result = $db->query($query);
echo "<br>You have searched for keywords: " . $_POST['keyword'];
if(mysqli_num_rows($result) > 0) {
$row_count=0;
echo "<br>Result Found: ";
echo "<br><table border='1'>";
While($row = $result->fetch_assoc()) {
$row_count++;
echo "<tr><td> ROW ".$row_count." </td><td>". $row['field1'] . "</td></tr>";
}
echo "</table>";
}
else {
echo "<br>Result Found: NONE";
}
}
You need to use UNION to get the records and show data like below
$aMust = explode(" ", $_POST['must']);
$aKeyword = explode(" ", $_POST['keyword']);
$query ="SELECT * FROM table1 WHERE (";
for($i = 0; $i < count($aMust); $i++) {
if( $i!=0 && $i != (count($aMust)-1) ) {
$query .=" AND ";
}
if(!empty($aMust[$i])) {
$query .=" field1 like '%" . $aMust[$i] . "%' ";
}
}
$query .=" ) ";
if( count($aKeyword) > 0 ) {
$query .= " AND (";
for($i = 0; $i < count($aKeyword); $i++) {
if( $i!=0 && $i != (count($aKeyword)-1) ) {
$query .=" OR ";
}
if(!empty($aKeyword[$i])) {
$query .= " field1 like '%" . $aKeyword[$i] . "%'";
}
}
$query .= " ) ";
}
$query .=" UNION ";
$query .=" SELECT * FROM table1 WHERE (";
for($i = 0; $i < count($aMust); $i++) {
if( $i!=0 && $i != (count($aMust)-1) ) {
$query .=" AND ";
}
if(!empty($aMust[$i])) {
$query .=" field1 like '%" . $aMust[$i] . "%' ";
}
}
$query .=" ) ";
This will give you those records which matches the optional values and which do not matches the optional values but matches the must values.
UNION do not gives duplicate records, so you don't have to worry for duplicate values coming.
In case any issue, let me know in comments.

php Search engine the keywords are not working

When i would search for the keywords that i have specified in my database it will return everything from my database not just the corresponding links that have the keywords attached to the link. here is my code
<?php
$q = $_GET['q'];
$terms = explode(" ", $q);
$query = "SELECT * FROM search ";
foreach ($terms as $each){
$i=0;
$i++;
if ($i == 1)
$query .= "keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
//connect
mysql_connect("localhost", "root", "");
mysql_select_db("search");
$query = mysql_query("SELECT * FROM search");
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
echo "<h3><a href='$link'>$title</a></h3><h4>$link</h4>$description<br /><br />";
}
}
else
echo "<b>No Results Found</b><br><br>Suggestions:<br>
Make sure all words are spelled correctly.<br>
Try different keywords.<br>
Try more general keywords.";
//disconnect
mysql_close();
?>
<?php
$q = $_GET['q'];
$terms = explode(" ", $q);
//connect
mysql_connect("localhost", "root", "");
mysql_select_db("search");
$query = "SELECT * FROM search ";
$i=1;
foreach ($terms as $each){
if ($i == 1) {
$query .= "WHERE ";
$query .= "keywords LIKE '" . mysql_real_escape_string("%" . $each . "%") . "' ";
} else {
$query .= "OR keywords LIKE '" . mysql_real_escape_string("%" . $each . "%") . "' ";
}
$i++;
}
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows > 0){
while($row = mysql_fetch_assoc($query)){
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
echo "<h3><a href='$link'>$title</a></h3><h4>$link</h4>$description<br /><br />";
}
} else {
echo "<b>No Results Found</b><br><br>Suggestions:<br>
Make sure all words are spelled correctly.<br>
Try different keywords.<br>
Try more general keywords.";
}
//disconnect
mysql_close();
?>
Fixes:
1) Removed second $query that was being defined. It selected all rows.
2) Moved initial $i declaration. It was being set back to 0 each loop.
3) Added WHERE
4) Moved $i++ after the if statement and set initial $i to 1.
5) Added mysql_real_escape_string so that data is escaped properly.
Recommendations:
I highly recommend taking a look at MySQLi (http://us2.php.net/mysqli) or PDO (http://us3.php.net/pdo)
Please let me know if this works or if you need further assistance.
A first sight, i see a couple of errors.
$i=0;
$i++;
if ($i == 1)
$i Will ALWAYS be one are.
you might want to move $i = 0; BEFORE the foreach
$query = mysql_query("SELECT * FROM search");
You build a query, but in the end you're not using it. you probably want to do : $query = mysql_query($query); instead. ( and also for code clarity using a different variable name for the output ? ) .
mysql_query is deprecated. Useless you're in a hurry, check PDO
First, you're missing the WHERE keyword before the conditions. So it should be:
foreach ($terms as $i => $each){
$each = mysql_real_escape_string($each); // Prevent SQL injection
if ($i == 0)
$query .= "WHERE keywords LIKE '%$each%' ";
else
$query .= "OR keywords LIKE '%$each%' ";
}
You don't need to increment your own counter variable, you can use the array indexes from $terms.
Second, after all that work to create $query, you're not using it. You wrote:
$query = mysql_query("SELECT * FROM search");
That should be:
$query = mysql_query($query);
BTW, it's generally a bad idea to reuse variables like that, it gets confusing when you use the same variable for different things. I suggest you call the second $query something like $results.
Change this line
$query .= "keywords LIKE '%$each%' ";
By
$query .= " Where keywords LIKE '%$each%' ";
And also cnhange this line
$query = mysql_query("SELECT * FROM search");
By
$query = mysql_query($query);

How to limit the amount of search results on each page like Google?

I am trying to limit the amount of search results on each page like Google does. I am also using a SQL database to organize my keywords and everything. Here is my code
<?php
$q = $_GET['q'];
$terms = explode(" ", $q);
//connect
mysql_connect("localhost", "root", "") or die ("Could Not Connect");
mysql_select_db("search") or die ("Could Not Connect To database");
$query = "SELECT * FROM search ";
$i=1;
foreach ($terms as $each){
if ($i == 1) {
$query .= "WHERE ";
$query .= "keywords LIKE '" . mysql_real_escape_string("%" . $each . "%") . "' ";
} else {
$query .= "OR keywords LIKE '" . mysql_real_escape_string("%" . $each . "%") . "' ";
}
$i++;
}
$query = mysql_query($query);
$numrows = mysql_num_rows($query);
if ($numrows > 0)
{
while($row = mysql_fetch_assoc($query))
{
$id = $row['id'];
$title = $row['title'];
$description = $row['description'];
$keywords = $row['keywords'];
$link = $row['link'];
echo "<h3><a href='$link'>$title</a></h3><h4>$link</h4>$description<br /><br />";
}
} else {
echo "<b>No Results Found</b><br><br>Suggestions:<br>
Make sure all words are spelled correctly.<br>
Try different keywords.<br>
Try more general keywords.";
}
//disconnect
mysql_close();
?>
After your foreach ($terms as $each){} you need to add an ORDER BY and LIMIT to the query, like so:
$query .= "ORDER BY keywords LIMIT 0, 10";
That will give you the first 10 results. Alter the LIMIT vars as needed. The first number is the offset (zero based, aka first result is 0, sixth result is 5) and the second number is the number of rows to return.
The ORDER BY helps with consistent results. You don't need it, but sometimes results can be weird.
See this question for more info if you need it.

While Loop in SQL query

I'm not sure why this SQL query is not working.
I'm new to SQL/PHP so please forgive.
mysql_query("
SELECT * FROM table WHERE name = " . "'Bob'" .
while($i < $size)
{
$i++;
echo "OR name = '";
echo $array[$i] . "'";
} .
" ORDER BY id DESC "
);
Dreamweaver gives me an error saying it is not correct but does not tell me what is wrong.
Is it possible to put a while loop into an sql command?
you can not use a while in a string
$where = "";
if ($size > 0)
{
$where .= " WHERE ";
}
while($i < $size)
{
$i++;
$where .= "OR name = '".$array[$i]."' ";
}
$query = "SELECT * FROM table WHERE name = '".Bob."'".$where." ORDER BY id DESC";
mysql_query($query);
(this code is not tested)
Woot !
You just can't write this :D
Build your OR condition before writing the query and it will be just fine:
$myCondition = " ";
while($i < $size) {
$i++;
$myCondition .= "OR name = '" . $array[$i] . "'";
}
mysql_query(
"SELECT * FROM table WHERE name = " . "'Bob'" . $myCondition . " ORDER BY id DESC ");
echo is to output the string, and it won't return the string.
Something like $str = "aaa" . echo "bbb"; won't work.
For you case, use IN will be better.
foreach ($array as &$name) {
$name = "'".mysql_real_escape_string($name)."'";
}
mysql_query("SELECT * FROM table WHERE name IN (".implode(',', $array).")");
Or use
"SELECT * FROM table WHERE name IN(".implode( ',', $array).")";

Categories