PDO - Search is querying terms as whole rather than each term separately - php

I currently have a simple search engine which searches a column in my database based on input from a user:
$search = $_GET['search'];
$terms = explode(" ", $search);
$sql = "SELECT * FROM people WHERE lname LIKE :search";
$q = $conn->prepare($sql) or die("failed!");
$q->bindValue(':search',"%".$search."%",PDO::PARAM_STR);
$q->execute();
if ($q){
//
do something
}
Currently it is searching for terms as a whole, for example "red desk" returns a result BUT "desk red" does not return anything
Any ideas? Any help much appreciated!
EDIT:
I have since changed it to this...
$search = $_GET['search'];
$terms = explode(" ", $search);
$sql = "SELECT * FROM people WHERE MATCH (lname,fname) AGAINST (:search IN BOOLEAN MODE)";
$q = $conn->prepare($sql) or die("failed!");
$q->bindValue(':search',"%".$search."%",PDO::PARAM_STR);
$q->execute();
it seems to be working okay for now, if anyone could suggest a better solution i would be very thankful!

This might not be the best way but I think something like this might do the job. I would myself love to know if there's a smarter way to do this!
$search = $_GET['search'];
$terms = explode(" ", $search);
$sql = "SELECT * FROM people"
if(count($terms) > 0) {
$sql .= " WHERE (lname LIKE '%:term_0%' OR fname LIKE '%:term_0%')";
for($i = 1; $i < count($terms); $i++)
$sql .= " AND (lname LIKE '%:term_" . $i . "%' OR fname LIKE '%:term_" . $i . "%')";
}
$q = $conn->prepare($sql) or die("failed!");
for($i = 0; $i < count($terms); $i++)
$q->bindValue(':term_' . $i, $terms[$i]);
$q->execute();

Related

PHP SQL Query for autocomplete

I have a MySqL DB with a table of Properties NAMES(can be more then one word) and I want to run a query to get results for the user text inputs to use for an autocomplete field.
The query I currently use is:
$query = "SELECT * FROM table WHERE LOWER(name) LIKE '%$value%' LIMIT 7";
But it is not good enough.
I tried splitting the input $value but for some reason is not working:
$values = explode(" ", $value);
$str = "";
for($i = 0; $i < count($values); ++$i)
{
if( $i == 0)
$str .= "LOWER(name) LIKE '%&$values[$i]%' ";
else
$str .= "AND LOWER(name) LIKE '%$values[$i]%' ";
}
$query = "SELECT * FROM table WHERE ". $str . " LIMIT 7";
Do you have any suggestions?
TX in advance.
Do OR instead of AND in your query:
$str .= "OR LOWER(name) LIKE '%$values[$i]%' ";

MYSQL LIKE but not equal

I have got database with this structure
Id Country Interests
12 Azerbaijan Acting,Reading
14 Azerbaijan Reading,Writing
16 Azerbaijan Acting,sleeping
And this PHP/MYSQL
$Interests = "Acting,Reading";
$Country = "Azerbaijan";
$query = "SELECT * FROM user_opt WHERE Country='$country' AND Interests='$Interests' ";
$i = substr_count($Interests,',');
for($j = 0; $j <= $i; $j++) {
$a = explode(',', $Interests);
$query2 = "SELECT * FROM user_opt WHERE Country='$country' AND Interests LIKE '%{$a[$j]}%'";
}
So with this code it returns me this ids
12
12
16
12
14
But i want it to return
12
16
14
You probably want to use OR to find all of your interests. To do that, build up your OR statement first, then insert it into the query. NOTE: This is not a secure/preferred way of doing this! Make sure you're using PDO or mysqli and bind your parameters!
$interestArr = [];
foreach($Interests as $Interest) {
$interestArr[] = "Interests LIKE '%{$Interest}%'";
}
$query2 = "SELECT * FROM user_opt WHERE Country='$country' AND (".implode(' OR ',$interestArr).")";
you can avoid the loop using a regexp
SELECT distinct *
FROM user_opt
WHERE Country='$country' AND Interests REGEXP 'Acting|Reading';
I did it using
!=
Like this
$query2=$con->query("SELECT * FROM user_opt WHERE Country='$country' AND Interests!='$Interests' AND Interests LIKE '%{$a[$j]}%'") or die($con->error);
you don't need to loop the result, just using OR comparator
$Interests = "Acting,Reading";
$Country = "Azerbaijan";
$query = "SELECT * FROM user_opt WHERE Country='$country' AND ("
$a = explode(",", $Interests);
$interestQuery = "";
for($j = 0; $j < count($a); $j++) {
if($j+1 == count($a))
$interestQuery = $interestQuery . "Interests LIKE '%". $a[$j] ."%') "
else
$interestQuery = $interestQuery . "Interests LIKE '%". $a[$j] ."%' OR"
}
$query = $query.$interestQuery;
$echo $query;

MySQL function giving wrong value

I am creating a search engine whereby I require videos to be displayed according to the keywords input.
So for my codes, I have
$search_exploded = explode (" ", $search);
foreach($search_exploded as $search_each){
$x = 0;
$x++;
if($x>=1){
$construct ="keywords LIKE '%$search_each%'";
}
else{
$construct ="OR keywords LIKE '%$search_each%'";
}
$x = 0;
}
and
$query ="SELECT * FROM test WHERE $construct";
$runquery = mysql_query($query);
$foundnum = mysql_num_rows($runquery);
The problem lies in the $runquery as my the error i get from my browser states that the line $foundnum = mysql_num_rows($runquery); is returning a Boolean value instead of the supposed resource type value.
Can anyone help fix this? I'm stuck on this for quite some time now. Thankful for and appreciate any help!
there is a problem in if condition and every time you set $x to 0 , then why you init it.
$x = 0;
foreach($search_exploded as $search_each){
if($x==0){
$construct =" keywords LIKE '%$search_each%' ";
}else{
$construct .=" OR keywords LIKE '%$search_each%' ";
}
$x++;
}
Try this .
You have a couple of logical errors inside your foreach loop pertaining to the $x variable.
Here is a simple way to achieve what you are trying to do (without using some kind of flags like $x)-
$search_exploded = explode (" ", $search);
// An array for the `LIKE` conditions
$construct_list = [];
// Adding the conditions in the array
foreach($search_exploded as $search_each){
$construct_list[] = "keywords LIKE '%$search_each%'";
}
// Joining them using OR
$construct = implode(" OR ", $construct_list);
// Supposing there are no keywords, the
// WHERE should not exist. So make a separate var for that -
$where_clause = "";
if(trim($construct) != ""){
$where_clause = "WHERE $construct";
}
// Perform your query
$query ="SELECT * FROM test $where_clause";
Try this:
$search_exploded = explode (" ", $search);
$construct = '1';
if (!empty($search_exploded)) {
$construct = '';
foreach($search_exploded as $search_each){
$construct .= $construct == '' ? " keywords LIKE '%$search_each%'" : " OR keywords LIKE '%$search_each%'";
}
}
$query ="SELECT * FROM test WHERE $construct";
$runquery = mysql_query($query);
if ($runquery) {
$foundnum = mysql_num_rows($runquery);
}
You seem to try to omit the OR for the 2nd and subsequent runs around the loop, but keep it for the first. should be the other way round,.
But I would probably avoid using the loop, and just use implode. Something like this (although would need to escape the values before using them in the query).
$search_exploded = explode (" ", $search);
if (count($search_exploded) > 0)
{
$construct = implode("%' OR keywords LIKE '%", $search_exploded);
$query ="SELECT * FROM test WHERE keywords LIKE '%".$construct."%'";
$runquery = mysql_query($query);
$foundnum = mysql_num_rows($runquery);
}

How to eliminate duplicate search results in MySQL?

I am having some trouble displaying text from database using PHP and SQL. Below is a script similar to what I have.
$search_split = explode(" ", $search); //$search is what user entered
foreach ($search_split as $searcharray) {
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE '%$searcharray%'");
while($info = mysqli_fetch_array($searched)) {
echo $info['description'];
}
}
So, for example the user enter 'He is male'. I split the word into three part 'He', 'is' and 'male' using 'explode' function. After that, I search the database for words that is similar to those three word. However, if a row have all the three words, it would display the row three times. How can I make it to display only once?
You could do something like this:
$search = 'test search me';
$search_split = array_map(function($piece) use ($mysqli_connection){
return "'%" . $mysqli_connection->real_escape_string($piece) . "%'";
}, explode(' ', $search)); //$search is what user entered
$search_split = implode(' OR `description` LIKE ', $search_split);
$sql = "SELECT * FROM people WHERE `description` LIKE $search_split";
echo $sql; // SELECT * FROM people WHERE `description` LIKE '%test%' OR `description` LIKE '%search%' OR `description` LIKE '%me%'
$searched = mysqli_query($connect, $sql);
Can you use full text search?
Add a full text index to the table
ALTER TABLE people ADD FULLTEXT(description);
Then you can use a query like this
SELECT *
FROM people
WHERE
MATCH ( description )
AGAINST ('+He +is +male' IN BOOLEAN MODE)
First store your results into one array then display it. Refer below code.
$search_split = explode(" ", $search); //$search is what user entered
foreach ($search_split as $searcharray) {
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE '%$searcharray%'");
while($info = mysqli_fetch_array($searched)) {
$results[$info['YOUR_PRIMARY_KEY']] = $info['description']; // this will over write your previous record
}
}
foreach($results as $result){
echo $result;
}
Now every records display only once.
You have put your db query in a foreach loop, which loops 3 times (with the current data: he, is and male). What you want to do is put all the search variables in one query, something like:
$search_split = explode(" ", $search); //$search is what user entered
$querypart = "'%" . implode("%' AND '%", $search_split) . "%'"; // use OR or AND, to your liking
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE " . $querypart);
while($info = mysqli_fetch_array($searched)) {
echo $info['description'];
}
This does not take any escaping/sanitizing of the query input, be aware...
$result = array();
$search_split = explode(" ", $search); //$search is what user entered
foreach ($search_split as $searcharray) {
$searched = mysqli_query($connect, "SELECT * FROM people WHERE `description` LIKE '%$searcharray%'");
while($info = mysqli_fetch_array($searched)) {
$result[] = $info['description'];
}
}
$finalres = array_unique($result);
so, finalres contains unique results
for($i = 0; $i < count($finalres); $i++)
echo $finalres[$i];

For loop getting out of control?

I have put together a for loop for a small search function I am building.
The code is as follows
$keyword = explode("+", $keywords);
for($i=0; $i <= count($keyword); $i++){
//check user table
$q = "SELECT id, username FROM ".TBL_USERS." WHERE username LIKE '%$keyword[$i]%'";
$result = $database->query($q);
while($row=mysql_fetch_assoc($result)){
extract($row);
echo "<a href='/profile.php?id=$id'>$username</a>";
}
}
When this runs, it is somehow retrieving all of the users from the database.
Is there any obvious reason for this?
If $keywords = "gregg"; , would this still work as there wouldn't be a + sign (only one word). Either way, this still doesn't work when it has multiple words involved!
I can confirm the query works perfectly if the term 'gregg' is passed into it.
Thanks for reading, hope you can help.
Your for loop looks like:
for ($i=0; $i <= count($keyword); $i++)
This is going past the end of $keyword by one, so the last query the loop executes is "LIKE '%%'" which would return every row. To fix this, change it to:
for ($i=0; $i < count($keyword); $i++)
Also, you cannot do "$keyword[$id]". It must be "{$keyword[$i]}"
your index has count($keyword) - 1, not count($keyword);
$keyword = explode("+", $keywords);
for($i=0; $i <= count($keyword) - 1; $i++){
//check user table
$q = "SELECT id, username FROM ".TBL_USERS." WHERE username LIKE '%".$keyword[$i]."%'";
$result = $database->query($q);
while($row=mysql_fetch_assoc($result)){
extract($row);
echo "<a href='/profile.php?id=$id'>$username</a>";
}
}
and changed quotes
try this
$q = "SELECT id, username FROM ".TBL_USERS." WHERE username LIKE '%{$keyword[$i]}%'";
or better this
$q = "SELECT id, username FROM ".TBL_USERS." WHERE username LIKE '%" . $keyword[$i] . "%'";
Consider use OR in the sql:
$keyword = explode("+", $keywords);
$keywords = array_map("mysql_real_escape_string", $keywords);
$q = "SELECT id, username FROM user WHERE username LIKE '%" . implode("%' OR username LIKE '%", $keywords) . "%';";
$result = $database->query($q);
while($row = mysql_fetch_assoc($result))
{
extract($row);
echo "<a href='/profile.php?id=$id'>$username</a>";
}

Categories