I have to following situation: I'm making a search page. The search page is populated with MySQL select query selectboxes. Therefor the name of the checkboxes are like name="name[]".
To show you what I'm doing, I'll include a picture:
So if I were to check 1 Availability - like Week - the query will work perfectly. But if I choose 2 Availabilities, only the models with BOTH availabilites show instead of every model that has one of both availabilities.
Here is my code:
HTML:
$return2 = $tafel->query("SELECT DISTINCT whenpossible FROM models where arttype LIKE 'Model%'");
while($row1 = $return2->fetch(PDO::FETCH_ASSOC)){
$whenp = $row1['whenpossible'];
<input type="checkbox" name="when[]" value="<?= $whenp ?>"><span class="box2"><?= $whenp ?></span>
PHP:
if (!empty($_POST['gender'])) {
$genders = $_POST['gender'];
$gender = implode(",",$genders);
} else {
$gender = "%";
}
$select = $tafel->prepare("SELECT * FROM models
WHERE whenpossible LIKE :when");
$select->bindParam(':when', $when, PDO::PARAM_STR);
$select->execute();
Does anyone have an idea how to fix this so that I can choose either 1 or multiple options?
Thank you all very much!
In code you build incorrect SQL command.
For your example SQL is
SELECT * FROM table WHERE field LIKE '%value1,%value2'
This is wrong code. Correct code can be
SELECT * FROM table WHERE field LIKE '%value1' OR field LIKE '%value2'
You should rewrite your code for build correct SQL
For those who are interested or facing the same problem, here is the answer:
In case IN or FIND_IN_SET aren't working for you, you can try this.
Implode your value like so:
if (!empty($_POST['VALUE'])) {
$value = $_POST['VALUE'];
$valueimplode = implode('|', $value)
} else {
$value = 'somethingelse'
}
| is very important for the SQL function. It acts like OR.
SQL as followed:
$query = $db->prepare("SELECT * FROM table WHERE column REGEXP(:valueimplode)");
$query->bindParam(':value', $valueimplode, PDO::PARAM_STR);
$query->execute();
You will find all the results that you need.
If you have an empty value, you can do this:
if (!empty($_POST['VALUE'])) {
$value = $_POST['VALUE'];
$valueimplode = implode('|', $value)
} else {
$value = '%' <-- Wildcard, means EVERYTHING!!!
}
Then the SQL like this:
$query = $db->prepare("SELECT * FROM table WHERE (column REGEXP(:valueimplode) OR column LIKE :value)");
$query->bindParam(':value', $valueimplode, PDO::PARAM_STR);
$query->execute();
% doesn't work with REGEXP so it will go to LIKE, which will then select everything in that column. Meaning, it will result everything.
I hope someone has good use for this!
Related
I have a web application and I'm trying to modify one of the queries. The query fetches information (from a table named voyage_list) and returns various fields.
I want to modify the query so that it is based on certain filters the user applies (which will be placed in the URL).
I can't get the query to work in the web application, but if I copy the query and execute it directly within PHPMyAdmin, it works fine.
$vesselFilter = $_GET['vesselFilter'];
$vesselArray = explode(',', $vesselFilter);
$arrayCount = count($vesselArray);
$sqlExtend = ' status = 1 AND';
foreach ($vesselArray as $value) {
$i = $i + 1;
$sqlExtend .= " vesselID = '$value'";
if ($i < $arrayCount){
$sqlExtend .= " OR";
}
}
$newQuery = "SELECT * FROM voyage_list WHERE" . $sqlExtend;
echo $newQuery;
$query = $db->query($newQuery)->fetchAll();
I appreciate the above is pretty messy, but it's just so I can try and figure out how to get the query to work.
Any help would be greatly appreciated!
Thanks
That query probably doesn't return what you think it does. AND takes precedence over OR, so it will return the first vessel in the list if the status is 1, and also any other vessel in the list, regardless of status.
You'd do better to create a query with an IN clause like this:
SELECT * FROM voyage_list WHERE status = 1 AND vesselID IN(8,9,10)
Here's some code to do just that:
$vesselFilter = $_GET['vesselFilter'];
// Validate data. Since we're expecting a string containing only integers and commas, reject anything else
// This throws out bad data and also protects against SQL injection.
if (preg_match('/[^0-9,]/', $vesselFilter)) {
echo "Bad data in input";
exit;
}
// filter out any empty entries.
$vesselArray = array_filter(explode(',', $vesselFilter));
// Now create the WHERE clause using IN
$sqlExtend = 'status = 1 AND vesselID IN ('.join(',', $vesselArray).')';
$newQuery = "SELECT * FROM voyage_list WHERE " . $sqlExtend;
echo $newQuery;
$query = $db->query($newQuery)->fetchAll();
var_dump($query);
i've a problem with a search form. It works only if I use all the 4 fields, but if a leave a field empty the while loop echoes out all the table's records.
Can someone please help me?
This is my php code for the search function
<?php
if (isset($_POST['cerca'])){
$cerca_tt = $_POST['tt_carrier'];
$cerca_risorsa = $_POST['risorsa_cerca'];
$cerca_team = $_POST['team_cerca'];
$cerca_linea = $_POST['linea_cerca'];
$sql_cerca = "SELECT * FROM normal WHERE
tt LIKE '%".$cerca_tt."%'
OR risorsa LIKE '%".$cerca_risorsa."%'
OR team LIKE '%".$cerca_team."%'
OR linea LIKE '%".$cerca_linea."%'";
if($sql_cerca) {
$trovati = mysql_query($sql_cerca); ?>
if the POST is blank then the variable is blank thus everything will match like '%%'
for example if $cerca_tt is blank. your query would be
"SELECT * FROM normal WHERE tt like '%%'"
that matches everything.
create the query based on the POST response.
$sel = "SELECT * from normal";
//You will need to deal with the WHERE part of the query.
if (!empty($cerca_tt)){
$sel .= " OR tt like '%".$cerca_tt."'";
}
etc....///
If you only provide one search parameter and the rest are empty strings, which you wrap with %, you are effectively searching everything. You need to build up your query. For example (simple):
$sqlParts = [];
if(isset($_POST['tt_carrier'])) {
$sqlParts[] = "tt LIKE '%".$cerca_tt."%'";
}
if(isset($_POST['risorsa_cerca'])) {
$sqlParts[] = "risorsa LIKE '%".$cerca_risorsa."%'";
}
if(isset($_POST['team_cerca'])) {
$sqlParts[] = "team LIKE '%".$cerca_team."%'";
}
if(isset($_POST['team_cerca'])) {
$sqlParts[] = "linea LIKE '%".$linea_cerca."%'";
}
if(!empty($sqlParts)) {
$sql = "SELECT * FROM normal WHERE " . implode(' OR ', $sqlParts);
}
I have a search form with a possible 15 or so fields, however not all are required to carry out a search, for instance;
a user might search for a registered user in 'London' who works in 'Finance' but leave all other fields blank, such as $availability or $salary etc, so $_POST data may look something like:
$location = $_POST['location']; // Value - London
$sector = $_POST['sector']; // Value - Finance
$available = $_POST['available']; // Value - Any
$salary = $_POST['salary']; // Value - Any
Bearing in mind I may have another 12 or so 'Any' values from other fields, what is the best way to query the database (PHP/MySQL) to return results without looping through what would probably be dozens of queries.
To try and be a bit clearer, what i'd like is a query which would work something like (deliberate pseudo code):
SELECT * FROM table where location = 'location' AND if($availability !='Any') { available = '$available' } etc etc
Is something like this possible?
Or can I create a single string of all $_POST fields that !='Any' and then carry out a search on a row that contains all the words in the string (which I think would work in theory)?
I hope this makes sense to someone and you can point me in the right direction.
P.S. All $_POST is escaped and secured before interacting with database, just not included here :)
Try this:
$sql = "SELECT * FROM table where 1 ";
foreach ($_POST as $key => $post) {
if ($post != 'Any') {
$sql .= " AND $key = '$post' ";
}
}
// now you can run $sql against the database
Could you for argument sake collect all of the $_POST into a foreach($key=>$val) and then run the key through a switch or if statments that appends "AND x=x " to the statement?
Something like:
$sql = "SELECT * FROM table WHERE required='required'";
foreach($_POST as $key=>$val){
if(!empty($val)){ $sql .= " AND ".$key."='".$val"'"; }
}
Not sure if that works but in theory that is what i thought of first.
Thanks to those who offered answers, however I used the suggested answer found in the link above my question as it was clearer to me. Sample code pasted below FYI:
$tmp = "where ";
if($A and $A!="any" and $A!="not used")
$tmp .= "row1 = '".$A."'";
if($B and $B!="any" and $B!="not used")
$tmp .= "AND row2 = '".$B. "'";
if($C and $C!="any" and $C!="not used")
$tmp .= "AND row3 = '".$C."'";
$db_q = "Select * from table $tmp";
Thanks again, don't know where I'd be without SO.
I have this code above which i use to implode some variable.
The issue is that i need to create the same thing for $hostess_name[] as i did for $hostess_id_selected[].
I don't know what am i doing wrong.
I need to implode it the same way as i did with $hostess_id_selected1
foreach($hostess_id as $val) {
$hostess_id_selected[] = $val;
$sqlnomehostess="SELECT nome_hostess FROM hostess where id='$val'";
$resultnomehostess=mysql_query($sqlnomehostess)or die(mysql_error());
$hostess_name= array();
while ($row=mysql_fetch_array($resultnomehostess,MYSQL_ASSOC)) {
$hostess_name[] = $row['nome_hostess'];
}
}
$hostess_id_selected1 = implode("-",$hostess_id_selected);
you have $hostess_name= array(); inside the loop. move it above
EDIT:
some tips:
foreach($hostess_id as $val) {
$hostess_id_selected[] = $val;
// this is pointless, i mean - you are recreating $hostess_id
btw, just a little tip for improvement - instead of running many SQL queries you can use a single query:
$sql = "SELECT GROUP_CONTACT(`nome_hostess` SEPARATOR '-') AS name_list
FROM `hostess`
WHERE id IN (".implode(',',$hostess_id).")";
if the items in $hostess_id are not necessarily numeric:
$sql_ids = array();
foreach($hostess_id as $id)
$sql_ids[] = mysql_real_escape_string($id);
$sql = "SELECT GROUP_CONTACT(`nome_hostess` SEPARATOR '-') AS name_list
FROM `hostess`
WHERE id IN (".implode(',',$sql_ids).")";
and after that:
the sql query returns 1 row with a column called "name_list", which contains the names joined with "-".
if you want to maintain the order of the id and name - you should do:
$sql = "SELECT
GROUP_CONTACT(`nome_hostess` SEPARATOR '-') AS name_list,
GROUP_CONTACT(`id` SEPARATOR '-') AS id_list
FROM `hostess`
WHERE id IN (".implode(',',$hostess_id).")";
implode is a basic function of php. It always work perfect.
Just check your array $hostess_id_selected, what it returning.
I think it will help you.
I have some search functionality that works with 3 drop down boxes. Based on the criteria chosen, a profile is returned. The 3 drop downs are:
County
Constituency
Gender
Now I am trying to build a query but have just realised that actually a person does not have to choose an option from each drop down and nor do I want them to.
So for instance I do not want to disable the search button until an option is selected from each drop down.
Having chosen a value from any drop down, and possibly having no value selected from any drop down at all, and just clicking the search button, I am trying to understand how I can cope with the unknown combinations.
My first thought was that I could use something like a truth table but I imagine this is simply overkill and in fact this is a very common piece of functionality.
Then I thought maybe I could have something like:
$county = "$_GET['county'];";
$constituency = "$_GET['constituency'];";
$gender = "$_GET['gender'];";
Then I could check to see if they are empty and somehow use this value, e.g.
if($county !== '') {
???SOMEHOW MAKE USE OF THIS IN AN SQL QUERY???
PERHAPS PASS IT TO ANOTHER PARAMETER
$sqlparams = "county = '$county'";
}
SELECT * FROM profile
WHERE {$sqlparams};
I think I'm on the right tracks but could use some guidance.
All help is greatly appreciated.
This should do want you want, I think.
<?php
$tooLookFor = array("county", "constituency", "gender");
foreach($tooLookFor as $key){
if(isset($_GET[$key]) && strlen($_GET[$key])>0){
$queryParams[] = $key.'="'.$_GET[$key].'"';
}
}
$query = "SELECT * FROM profile WHERE ".implode(' AND ', $queryParams);
?>
You could do something like:
$county = $_GET['county'];
$constituency = $_GET['constituency'];
$gender = $_GET['gender'];
$sqlparams = array();
if($county !== '') {
$sqlparams[] = "county = '$county'";
}
if($constituency !== '') {
$sqlparams[] = "constituency = '$constituency'";
}
if($gender !== '') {
$sqlparams[] = "gender = '$gender'";
}
$query = "SELECT * FROM profile";
if (count($sqlparams) > 0) {
$query .= " WHERE " . implode(" AND ", $sqlparams);
}
You can do that with something like this:
$where = array();
//repeat as needed
$where[$column] = $value;
$where2 = array();
foreach($where as $key => $value){
$where2[] = "$key = '$value'";
}
$where_string = implode(' AND ', $where2);
$where_string will have the string to insert after WHERE.
Yes, you are on the right track, you're just not at the right switch yet. ;)
You can't build the query until you know what you have to work with. So first, in your validation, determine (as you are doing) with the key words actually are and what fields they represent. Presumably these map to fields in tables, maybe 3 tables? Point is, your query will need to be dynamically built.