Filter using PHP and MYSQL - php

I am an programming amateur, working on a small project of mine but i got stucked when I wanted make filters for my mysql output.
All works when I fill all search input fields and submit, correct filtered result appears. But when I leave one field out nothing shows up (only else command) as using AND condition. If I use OR and leave it empty it shows all result without caring what has been filled in the required fields.
Would there be any way how to show result even if one of the field stays empty? I tried to play with a code from different post here in stackoverflow but no luck yet as i am not really much experienced and cannot figure out how to use this inside of my code.
if(isset($_POST["profilename"]) && $_POST["profilename"] != "")
$sql .= " AND profilename = '". $_POST["profilename"] ."'";
Below here is my code, if you could have a look and suggest what i could edit so the filtering would be working.
<select class="form-control" id="Select1" name="departure">
<select class="form-control" id="Select2" name="destination">
<select class="form-control" id="Select3" name="layover">
...
<?php
include_once("connect.php");
if (isset($_GET['submit'])) {
$departure = mysqli_real_escape_string($connection, $_GET['departure']);
$destination = mysqli_real_escape_string($connection, $_GET['destination']);
$layover = mysqli_real_escape_string($connection, $_GET['layover']);
$result = mysqli_query($connection, "SELECT * FROM crud
WHERE departure LIKE '$departure%'
AND kam LIKE '$kam'
AND layover LIKE '$layover'
ORDER BY id DESC");
if($make = mysqli_num_rows($result) > 0){
while($r = mysqli_fetch_assoc($result)){
echo '<div style="display:block;"'.$r['departure'].'</div>';
echo '<div style="display:block;"'.$r['kam'].'</div>';
echo '<div style="display:block;"'.$r['layover'].'</div>';
//following code..
}
}else{
echo'<h4>No match found!</h4>';
print ($make);
}
mysqli_free_result($result);
mysqli_close($connection);
}
?>
For example: Filter Departure with Destination and leave Layover empty -> should return a result of desired Departure and Destination with ANY Layover.
or 2nd example: Fill Destination with Layover but leave Departure empty would result in desired search of Destination and Layover with ANY Departure.
Please let me know if its possible with my code and possibly how.
Thank you so much guys!!

You can check each input against an empty string in an OR condition within each of the different AND conditions.
"SELECT * FROM crud
WHERE ('$departure' = '' OR departure LIKE '$departure%')
AND ('$kam' = '' OR kam LIKE '$kam')
AND ('$layover' = '' OR layover LIKE '$layover')
ORDER BY id DESC"
This way, if one of the input parameters isn't given, the corresponding part of the condition will be interpreted as, for example, ('' = '' OR departure LIKE '$departure%') which will evaluate as true for every row since '' always equals '' regardless of the LIKE comparison.
A couple of notes - first, without any wildcard characters, your LIKE comparisons basically work like =, (e.g. kam LIKE '$kam' will match the same rows as kam = '$kam'). So either just use = or add some wildcards in order for those to be useful.
Second, consider using prepared statements instead of concatenating values into your SQL like this. The concatenation approach makes your code vulnerable to SQL injection and various annoying errors (even if you escape the strings).

something like this:
$result = mysqli_query($connection, "SELECT * FROM crud
WHERE (departure LIKE '$departure%' OR departure is null)
AND kam LIKE '$kam'
AND (layover LIKE '$layover' OR departure is null)
ORDER BY id DESC");

Let's put the "dont build your queries using user input" aside.
If you want to go that path, you could use conditionals to build the query step by step.
$query = "SELECT * FROM crud WHERE ";
if (!empty($departure)) {
$query .= "departure LIKE '$departure%' AND ";
}
if (!empty($destination)) {
$query .= "destination LIKE '$destination%' AND ";
}
if (!empty($layover)) {
$query .= "layover LIKE '$layover' AND ";
}
$query .= "1 ORDER BY id DESC";
You will end up with some alternatives in the $query string:
NOTHING SELECTED:
SELECT * FROM crud WHERE 1 ORDER BY id DESC
SOMETHING SELECTED:
SELECT * FROM crud WHERE departure LIKE '$departure%' AND layover LIKE '$layover' AND 1 ORDER BY id DESC
ALL SELECTED:
SELECT * FROM crud WHERE departure LIKE '$departure%' AND destination LIKE '$destination%' AND layover LIKE '$layover' AND 1 ORDER BY id DESC
This should cover it.
Have a good day

Related

What is the best query for php-mysql search?

I have a search engine which is pretty straight forward. The query is below.
$sql = "SELECT * FROM events WHERE eventname LIKE '%".$_POST["search"]."%'
OR place LIKE '%".$_POST["search"]."%'
OR country LIKE '%".$_POST["search"]."%'
OR date LIKE '%".$_POST["search"]."%'
LIMIT 40";
But, Problem with this is this,
if I put the 'eventname' in search-box it is okay and it saws data from eventname column correctly. Or if I search only for place or country or date individually, it shows data correctly. But, if I search (FOR EXAMPLE) for both eventname and place together search results shows nothing. Using this query what are the changes I have to make to get it working?
Additionally I want to say that I have seen some of the query like "MATCH ... AGAINST". Though I don't want to use that, but if there are no other way what could be that "MATCH...AGAINST" query for this?
Here is my full code. They are straight forward. And I am working on a weird client's project and he want it to be like this and security is not a fact for him. So, you might notice some security issue which will be solved later. but the query first.
<?php
include_once("admin/connection/db.php");
$output = '';
$sql = "SELECT * FROM events WHERE eventname LIKE '%".$_POST["search"]."%'
OR place LIKE '%".$_POST["search"]."%'
OR country LIKE '%".$_POST["search"]."%'
OR date LIKE '%".$_POST["search"]."%'
OR date AND country LIKE '%".$_POST["search"]."%'
OR date AND place LIKE '%".$_POST["search"]."%'
OR date AND eventname LIKE '%".$_POST["search"]."%'
LIMIT 40";
$result = mysqli_query($db, $sql);
if(mysqli_num_rows($result) > 0) {
while($row = mysqli_fetch_array($result)) {
$output .= "<a class='search-result' href='".$row["link_pdf"]."'><li><i class='fa fa-trophy'> </i> ".$row["eventname"].'<br/>'.date('Y-m-d', strtotime($row["date"])).' || '.$row["place"].', '.$row["country"].'<img src="logos/'.$row["country"].'.png" width="30px" height="18px;" /></li></a>';
}
echo $output;
}else {
echo "<li>No Data Found Macthing Your Query</li>";
}
?>
Here is the link where you can check it directly
http://speed-timing2.6te.net/
I believe your search query term is for example "event_name place_name" and in this case your query will not work. You can use FULLTEXT search instead.
For example
at first set fulltext index for eventname, place, country field as those are string fields.
$sql = "SELECT * FROM (
SELECT *, MATCH (eventname, place, country) AGAINST ('".$_POST["search"]."' IN BOOLEAN MODE) AS score
FROM events
ORDER BY score DESC
) AS temp
WHERE temp.score>0 OR temp.date LIKE '%".$_POST["search"]."%'
";
Please check manual here http://dev.mysql.com/doc/refman/5.7/en/fulltext-boolean.html

Group by week,month in mysql depending on php variable. If condition in group by

I have a table, prescription, which the fields
prescription_id
description
patient_id
pres_date
title
I know how to group by month, week or day. My question is, i want this to be dynamic. I have an interface in the UI where the user will select a category, month, day or week. Which i store in a variable $category. Is there any way to use an if condition in group by to see which category the user has selected, and return the sql query in that format.
For example, if the user selects month, in my sql query, i want it to return, group by month(pres_date), if the user selects day, i want sql to return group by day(pres_date).
You don't even need to use conditional logic. Just do something like this:
$sql = "SELECT * FROM prescription GROUP BY " . $category . "(pres_date)";
This way, your query gets built using one line. Of course, make sure you validate the value of $category before you run the query.
The code will be like this
if($_POST['select'] == 'month')
{
$sql = "select * from table group by month(pres_date)";
}
else if($_POST['select'] == 'day')
{
$sql = "select * from table group by day(pres_date)";
}
else
{
$sql = "select * from table group by week(pres_date)";
}
Simplest way to do this is in PHP, using if or switch statements:
$sql = "SELECT ... FROM ... ";
switch($category) {
case 'month':
$sql .= "GROUP BY month(pres_date)";
break;
case 'day':
$sql .= "GROUP BY day(pres_date)";
break;
//... etc ...
default:
//bad category value; do some error handling
}
// now do $mysqli->query($sql) or $PDO->query($sql)
It sounds like you've already got yourself going on the right path. You should be able to build the base form of the query and then modify it depending on the value that they have selected. Try doing something in that fashion where you add group by month(pres_date) if they select month, etc.
No need of multiple condition checking , get the selected option in variable and use it in sql query,
if(isset($_POST['selected_option']))
$grp_option=$_POST['selected_option'];
$sql = "SELECT .... GROUP BY".$grp_option."(pres_date)";

Search suggestion box inputs space in front of search query

We have a problem with our search suggestions. Everytime we click on a suggestion at our website, it puts a space in front of the search query, which causes the query to fail.
The code that we use for the suggestions is this:
$query = $db->query("SELECT DISTINCT productnaam FROM product WHERE merk LIKE '$queryString%' LIMIT 10");
if($query) {
// While there are results loop through them - fetching an Object (i like PHP5 btw!).
while ($result = $query ->fetch_object()) {
// Format the results, im using <li> for the list, you can change it.
// The onClick function fills the textbox with the result.
// YOU MUST CHANGE: $result->value to $result->your_colum
echo '<li onClick="fill(\''.$result->merk.' '.$result->productnaam.'\');">'
.$result->merk.' '.$result->productnaam.''.'</li>';
}
} else {
echo 'ERROR: There was a problem with the query.';
Try out with trim()
$queryString = trim($queryString);
The trim() function removes whitespaces and other predefined characters from both sides of a string.
try the trim() function as Sameera Thilakasiri specified below and also update your query to something like "SELECT DISTINCT productnaam FROM product WHERE merk LIKE '%$queryString%' LIMIT 10" The percent sign on both sides will ensure that your query will select records that contain your input as opposed to records that start with your input.
bellow is some further explanation on the SQL LIKE condition that might help you out
// This query will look for records that start with "sa"
select * from table where name like 'sa%'
// This query will look for records that contain "sa"
select * from table where name like '%sa%'
// This query will look for records that end with "sa"
select * from table where name like '%sa'
hope that helps!

mysql like statement is not working as expected

I have a table with 4 record.
Records: 1) arup Sarma
2) Mitali Sarma
3) Nisha
4) haren Sarma
And I used the below SQL statement to get records from a search box.
$sql = "SELECT id,name FROM ".user_table." WHERE name LIKE '%$q' LIMIT 5";
But this retrieve all records from the table. Even if I type a non-existence word (eg.: hgasd or anything), it shows all the 4 record above. Where is the problem ? plz any advice..
This is my full code:
$q = ucwords(addslashes($_POST['q']));
$sql = "SELECT id,name FROM ".user_table." WHERE name LIKE '%".$q."' LIMIT 5";
$rsd = mysql_query($sql);
Your query is fine. Your problem is that $q does not have any value or you are appending the value incorrectly to your query, so you are effectively doing:
"SELECT id,name FROM ".user_table." WHERE name LIKE '%' LIMIT 5";
Use the following code to
A - Prevent SQL-injection
B - Prevent like with an empty $q
//$q = ucwords(addslashes($_POST['q']));
//Addslashes does not work to prevent SQL-injection!
$q = mysql_real_escape_string($_POST['q']);
if (isset($q)) {
$sql = "SELECT id,name FROM user_table WHERE name LIKE '%$q'
ORDER BY id DESC
LIMIT 5 OFFSET 0";
$result = mysql_query($sql);
while ($row = mysql_fetch_row($result)) {
echo "id: ".htmlentities($row['id']);
echo "name: ".htmlentities($row['name']);
}
} else { //$q is empty, handle the error }
A few comments on the code.
If you are not using PDO, but mysql instead, only mysql_real_escape_string will protect you from SQL-injection, nothing else will.
Always surround any $vars you inject into the code with single ' quotes. If you don't the escaping will not work and syntax error will hit you.
You can test an var with isset to see if it's filled.
Why are you concatenating the tablename? Just put the name of the table in the string as usual.
If you only select a few rows, you really need an order by clause so the outcome will not be random, here I've order the newest id, assuming id is an auto_increment field, newer id's will represent newer users.
If you echo data from the database, you need to escape that using htmlentities to prevent XSS security holes.
In mysql, like operator use '$' regex to represent end of any string.. and '%' is for beginning.. so any string will fall under this regex, that's why it returms all records.
Please refer to http://dev.mysql.com/doc/refman/5.0/en/pattern-matching.html once. Hope, this will help you.

Search mySQL with PHP, using a WHERE wildcard or an IF statement?

I'm letting users search my database for data by city.
My query looks like:
$results = mysql_query("SELECT * FROM mydb WHERE City='".$city."' LIMIT 10");
I want a user to be able to search 'all cities', so I'd like to either remove the WHERE statement if $city=='all cities'; or use a wildcard for the WHERE statement that matches all cities in the db.
I used to have an IF statement that switched between two queries, but I want to add more filters like country/all countries, zipcode/all zipcodes, etc, So I'd rather keep one dynamic SQL query.
Well, you could still have just one query and build the where clause dynamically, as such:
$where = '';
// conditional statements (if/else, switch) for populating the where clause
$where .= " WHERE City = '{$city}'";
$where .= " AND Country = '{$country}'";
$results = mysql_query("SELECT * FROM mydb{$where} LIMIT 10");
One way would be a case statement:
WHERE City = case when '$city' = 'All cities' then City else '$city' end
If the user is searching for 'All cities', this turns the WHERE statement into:
WHERE City = City
Which is always true (at least for non-null cities ;))
P.S. Make sure you're running these queries using a read-only MySQL account. The user could enter funny stuff into the $city parameter!
You could try
WHERE City like '$city'
and permit the users to enter wildcards, if you think they'd be up to it.
although not PHP programmer, this pseudocode might offer an option... conditionally build out your where clause. Additionally, I would do it with parameterized queries instead of direct string building to prevent sql-injection attacks.
cYourSQL = "select * from YourTable where "
cAndRequired = ""
if city is NOT "all cities"
cYourSQL = cYourSQL + cAndRequired + " city = 'YourParameterValueProvided' "
cAndRequired = " AND "
endif
Now, always add your country selection
cYourSQL = cYourSQL + cAndRequired + " country = 'YourCountryValue' LIMIT 10 "
Run the query

Categories