Variable sql query depending on number of search parameter - php

I need to do a sql query in php for search some entries (so using WHERE). But the field used to search could be of variable number.
I have a page with a search form, with 4 Field. It sends via POST the fields to a search.php that make a query:
$gomme_sql = $data->query("SELECT * FROM table WHERE parameter1 = '$_POST['name1']' AND parameter2 = '$_POST['name2']' ORDER BY id ASC");
But I don't know which field are filled. So, if I don't enter anything in field1 from the search form, I shouldn't have parameter1 = '$_POST['name1']' in the WHERE query.
Have you any idea how to obtain this?
Thank you

You can check the post data before appending that clause to the query in a way like this:
edit: adding additional check:
$sql="select something from someTable ";
if(!empty($_POST['name1']) || !empty($_POST['name2'])) // add as many as you like
{
$sql.=" where ";
if(!empty($_POST['name1']))
{
$sql.="parameter1= $_POST['name1']";
}
// etc etc...
}
$sql.=" ORDER BY id ASC";
and so on.
Having said that, please, please use prepared statements with this sort of input from the user. This is SUPER open to sql injection. Please do read this: How can I prevent SQL injection in PHP?

You can write generic sql select function like this , if you need more complex SQL just modify it.
<?php
function sqlSelect($table, $sel, $wh = '', $groupby = '', $order = '', $add = '') {
$tb = $table;
if (is_array($table)) {
$tb = implode(',', $table);
}
if ($wh) {
if (is_array($wh)) {
$w = array();
foreach ($wh as $k => $v) {
$v = mysqli_real_escape_string($v);
if (is_null($v))
$w [] = "$k=null ";
else
$w [] = "$k ='$v'";
}
$wh = 'where ' . implode(' and ', $w);
}else {
$wh = "where $wh";
}
}
if ($groupby)
$groupby = "group by $groupby";
if ($order)
$order = "order by $order";
$sql = "select $sel from $tb $wh $groupby $order $add ";
return $sql;
}
//set _GET as this is console test
$_GET['name1']='Bob';
$where = array(
'name1'=>$_GET['name1']
);
echo sqlSelect('sometable' , '*' , $where) ."\n";
// select * from sometable where name1 ='Bob'
//or some complex stuff
echo sqlSelect('persons', "age,status" , array('name'=>'Maria' , 'likes'=>'PHP') , null, 'age' , 'limit 20');
//select age,status from persons where name ='Maria' and likes ='PHP' order by age limit 20

Related

How to enter variable into prepared stmt that will retrieve all from the column?

I'm making a search filter on my events website. There are 3 drop down inputs: Location, event type, date.
When the user submits the search filter, the form posts values that changes the mysql query which will display different events on the user screen. I'm having trouble finding a flexible solution.
Right now my query is like this:
$filter = $database->prepared_query("SELECT * FROM onlineevent WHERE event_location = (?) AND event_type = (?) AND event_date = (?)", array($l, $t, $d));
How can I make $l retrieve ALL possible values for event_location? The same goes for $t and $d. I thought I could set $l to '*' but that doesn't work.
The problem now is if the user doesn't select a value for $l, and they do select a value for $t and $d, then the query doesn't work. I want to set the default value for each variable to bring all results for each condition.
So if the user doesn't select any filter and submits the form, the query I'm looking for would look something like this:
$filter = $database->prepared_query("SELECT * FROM onlineevent WHERE event_location = (?) AND event_type = (?) AND event_date = (?)", array(ALL, ALL, ALL));
The original version of Ali_k's answer was almost right, but made the mistake of including the whole clause as a parameter, rather than just the value. That would cause the whole clause to be seen as a string value, rather than as code with values within it.
The idea of building up the string gradually - and, crucially, only adding a clause if there's actually value specified in the search parameters - is correct though. You also need need to build up the parameter array separately at the same rate.
Here's a version which should actually execute correctly:
$sql = "SELECT * FROM onlineevent";
$sqlfilters = "";
$parameters = array();
if( !empty($l) ){
$sqlfilters .= " event_location = ?";
$parameters[] = $l;
}
if( !empty($t) ){
$sqlfilters .= ($sqlfilters != "" ? " AND" : "")." event_type = ?";
$parameters[] = $t;
}
if( !empty($d) ){
$sqlfilters .= ($sqlfilters != "" ? " AND" : "")." event_date = ?";
$parameters[] = $d;
}
if ($sqlfilters != "") sqlfilters = "WHERE ".$sqlfilters; //add a WHERE clause if needed
$sql .= $sqlfilters; //add the filters to the initial SQL
$filter = $database->prepared_query($sql, $parameters);
Maybe I'm misunderstanding you but aren't you just looking for:
$filter = $database->prepared_query("SELECT * FROM onlineevent")
OR
$filter = $database->prepared_query("SELECT * FROM onlineevent WHERE event_location IS NOT NULL AND event_type IS NOT NULL AND event_date IS NOT NULL")
Your question is not quite clear and it is also not clear how the prepare function works, but here is my suggestion:
$array = array();
$query_parms = '';
if( !empty($l) ){
$array[] = $l;
$query_parms .= 'event_location = (?)';
}
if( !empty($t) ){
$array[] = $t;
$query_parms .= count($array) > 1 ? 'AND event_type = (?)' : 'event_type = (?)';
}
if( !empty($d) ){
$array[] = $d;
$query_parms .= count($array) > 1 ? 'AND event_date = (?)' : 'event_date = (?)';
}
$filter = $database->prepared_query("SELECT * FROM onlineevent WHERE " . $query_parms, $array);

Filtering data with Select (advanced) [duplicate]

This question already has answers here:
Search Form with One or More (Multiple) Parameters
(2 answers)
Closed 4 years ago.
I'm on a project and I have 3 possibilities of filters. Filter by name,cities and province. Right now what i'm doing are simple IFs trying to think of all possibilities.
Example : it can be [Name][City][All] or [All][City][province] or [All][All][province] and it goes on in total of 8 to 9 possibilities. That means if have to do about 8 condition in my PHP code trying to catch everything.
So my question is : Is there a way on MySql to do a SELECT data1.. FROM tableName WHERE ... but when I don't give for example the city it search only with the name and the province.
This could be done in mysql or php - but imho the php solution looks cleaner. To do this, you just have to build the query on runtime.
$name = ...
$city = ...
$province = ...
$fields = [
'name' => $name,
'city' => $city,
'province' => $province
];
$where = [];
$values = [];
foreach ($fields as $field => $value) {
if ($value) {
$where[] = "$field = :$field";
$values[$field] = $value;
}
}
$sql = 'SELECT * FROM table';
if (count($where) > 0) {
$sql .= ' WHERE ' . join(' AND ', $where);
}
// using pdo
$query = $pdo->prepare($sql);
$query->execute($values);
// ...
There's a couple of approaches. One way to do it is to dynamically build the SQL text. If the options are discrete, we can just handle each condition separately, and include or not. As an example of the pattern:
start the SQL text:
$sql = "SELECT ...
FROM ...
WHERE 1=1 ";
conditionally append search conditions
if( we need to add a condition on city ) {
$sql .= " AND t.city LIKE :city ";
}
if( we need to add a condition on province ) {
$sql .= " AND t.province LIKE :province ";
}
if( we need to add a condition on name ) {
$sql .= " AND t.name LIKE :name ";
}
finish the SQL text
$sql .= " ORDER BY ...";
prepare the SQL text (here is a good place to echo/var_dump/log the contents of $sql for debugging)
$sth = $dbh->prepare($sql);
conditionally bind values for any of the search conditions we added
if( we need to add a condition on city ) {
$sth->bindValue(':city',$city);
}
if( we need to add a condition on province ) {
$sth->bindValue(':province',$province);
}
if( we need to add a condition on name ) {
$sth->bindValue(':name',$name);
}
execute
$sth->execute();
Another alternative is to use static SQL with expression in the WHERE clause, using a "special" reserved value to represent "no search".
In this example, we are using a zero-length string represent "no search condition" ...
$sql = "SELECT ...
FROM ... t
WHERE ( :city1 = '' OR t.city LIKE :city2 )
AND ( :province1 = '' OR t.province LIKE :province2 )
AND ( :name1 = '' OR t.name LIKE :name2 )
ORDER BY ...";
$sth = $dbh->prepare($sql);
$sth->bindValue(':city1' , $city );
$sth->bindValue(':city2' , $city );
$sth->bindValue(':province1' , $province );
$sth->bindValue(':province2' , $province );
$sth->bindValue(':name1' , $name );
$sth->bindValue(':name2' , $name );
$sth->execute();
You could do something like this, storing your filters in an array and checking for the existence of each. If the filter has a value, dynamically add it to the where clause by using an array of where statements.
$filters = ['name', 'city', 'province'];
$where = [];
foreach($filters as $filter) {
if(!empty($_POST[$filter])) {
$param_name = ":{$filter}";
$where[] = "{$filter} = {$param_name}";
$params[$param_name] = $_POST[$filter];
}
}
$where_str = !empty($where) ? 'WHERE ' . join(' AND ', $where) : '';
$sql = "SELECT * FROM table {$where_str}";
$db = new PDO(<connection_str>);
$stmt = $db->prepare($sql);
$results = $stmt->execute($params);

SQLITE build query string from values passed

Hi have a function that gets passed strings via the below;
getFilterResults($id, $limit, $misc);
and in my function i connect to SQLite DB and build a query based on the values passed through, like so;
function getFilterResults($id, $limit, $misc) {
$dbConnect = new SQLite3(database);
if(!empty($limit) && !empty($id) && !empty($misc)){
$buildString = ('SELECT * FROM fields ORDER BY id DESC');
}else{
//no params filters arrived so dont filter - aka get all results
$buildString = ("SELECT * FROM fields ORDER BY id DESC");
}
$query = $dbConnect->query($buildString);
//...
}
Issue is how do I build the query if some of the values are empty and I have to decide which value uses/starts of the 'WHERE' query..obviously the first value return that is not null starts of the 'WHERE'..
I can see the long way would be to loop through each one and build - once the first value found that is not null and kick off from there but that seems unpractical and not good practice.
//check if limit set..
if($limit) {
$doLimit = 'LIMIT '.$limit.'';
}
WHERE 'id = '.id.' AND misc = '.$misc.' '.$doLimit.'
Your function taking in ($id, $limit, $misc) really prevents you from being able to do anything else than what you already are... I would recommend using prepared statements though
// Stores values for a prepared statement
$values = [];
$sqlite = new SQLite3(/* ... */);
$query = 'SELECT * FROM fields WHERE id = ? AND misc = ? ORDER BY id DESC';
$values[] = $id;
$values[] = $misc;
if ($limit) {
$query .= ' LIMIT ?';
$values[] = $limit;
}
// Use prepare and let SQLite3 escape the values for you
$stmt = $sqlite->prepare($query);
foreach ($values as $idx => $val) {
$stmt->bindValue($idx, $val);
}
$result = $stmt->execute();

How to build a dynamic mysql query to suit all users

I need your help with my website search functionality. I'm developing a members area wherein users can search other registered users based on certain criteria, or combination of criteria.
My problem now is how to build a dynamic mysql query to suit the need of each combination of search criteria, where the number of criteria is variable.
Normally, I can write with a pre-determined set of criteria using
WHERE param1 = '$param1'
AND param2 = '$param2'
AND param3 = '$param3'
How do I solve this problem?
If the issue is that you don't know which of the criteria the user will pick, but want to return results for "blank" criteria, you can use the following:
$criteria_1 = $_POST['criteria_1'];
$criteria_2 = $_POST['criteria_2'];
$criteria_3 = $_POST['criteria_3'];
if(!$criteria_1 && !$criteria_2 && !$criteria_1) {
echo "You must select at least one criteria!";
} else {
// Run query mentioned below and return results.
}
THe query would then look like:
SELECT * from mytable
WHERE
(criteria1 = '$criteria_1' OR '$criteria_1' = '') AND
(criteria2 = '$criteria_2' OR '$criteria_2' = '') AND
(criteria3 = '$criteria_3' OR '$criteria_3' = '')
This will treat any blank (non-selected) parameters as blank and ignore them. Be aware that with the above, if no criteria are given, it will return all results.
Another way to write the above is:
SELECT * from mytable
WHERE
criteria1 IN ('$criteria_1', '') AND
criteria2 IN ('$criteria_2', '') AND
criteria3 IN ('$criteria_3', '')
Again, allowing for no entry at all to return all criteria1 results.
Here's a generic example of what you're asking:
$query = "SELECT * FROM mytable";
if ($_POST['name'] == "Jack") {
$query .= " WHERE name = 'Jack'";
}
if ($_POST['name'] == "Bob") {
$query .= " WHERE name = 'Bob'";
}
if ($_POST['state'] != "") {
$query .= " AND state = '" . mysql_real_escape_string($state) . "'";
}
//So now, in total, your query might look like this
//"SELECT * FROM mytable WHERE name = 'Bob' AND state = '$state'"
$result = mysql_query($query);
You just add to your $query string with if statements, then execute the query once you've checked all $_POST variables.
I've seen queries like this, so that if you don't want to put in a value for a particular column, you pass in NULL for that column:
SELECT *
FROM users
WHERE param1 = :param1
UNION
SELECT *
FROM users
WHERE param2 = :param2
UNION
SELECT *
FROM users
WHERE param3 = :param3
This assumes that you'll have each column indexed and you're performing Boolean AND searches (and using PDO).
use your scripting language (php) to loop over the inputs...
then have a structure like this:
WHERE 1=1
then add your
AND paramx = '$px'
to it...
$criteria = array();
//Populate your criteria and parameter arrays with input from the web page here
...
// $criteria should now have stuff in it
$sql = "SELECT * FROM mytable ";//Or whatever your sql query is
$count = 0;
foreach ($criteria as $key => $parameter) {
if ($count == 0) {
$sql = $sql."WHERE ".$key." = ".$parameter;
} else {
$sql = $sql."AND ".$key." = ".$parameter;
}
$count++;
}
That said, this is highly vulnerable to sql injection attack. Try using PHP PDO
An option is also to build the query from php/asp or whatever you working with, like this
$param1 = (isset($searchParam1) ? "param1 = $searchParam2" : "1");
$param2 = (isset($searchParam2) ? "param2 = $searchParam2" : "1");
$param3 = (isset($searchParam3) ? "param3 = $searchParam3" : "1");
and the query would be like
SELECT ... WHERE $param1 $param2 $param3
would like to share this code to build dynamic mysql query with PHP
Thx & regards
$vocabulary = (($page == "vocabulary") ? "image_name <> ''" : "");
$groupcat = (($group != "") ? "group = $group" : "");
$var = array($vocabulary, $groupcat);
$counter = "0";
$param = "";
for ($i=0;$i<count($var);$i++)
{
if ($counter == "0" && $var[$i] != "" ) $param = "WHERE ";
if ($counter > "0" && $var[$i] != "" ) $param = " AND ";
if ($param != "")
{
$condition .= $param . $var[$i];
$param="";
$counter++;
}
}
echo "Condition : ". $condition;

How can execute a MySQL query with multiple WHERE-clauses?

how would you do a mysql query where a user can choose from multiple options. Fox example I have a form that user can use to search for houses. Now I have a select box where you can chosse whether you want a house, a flat or whatever. Then I have a second box where you can choose for example the city you want the house or flat to be in. And maybe another one with the maximum price.
Now how would you do the mysql query? My problem is, I would do it like that:
if($_POST["house_type"] != 0) {
$select = mysql_query("SELECT * FROM whatever WHERE type = '".$_POST["house_type"]."'");
}
But now I only have the case that someone has chosen a house type but not any other option. So do I have to do an "if" for every possible combination of selected elements?
To emphasize my problem:
if(!isset($_POST["house_type"])) {
if($_POST["something"] == 0) {
$search_select = #mysql_query("SELECT * FROM housedata WHERE something = $_POST["whatever"]);
}
elseif($_POST["something"] != 0) {
$search_select = #mysql_query("SELECT * FROM housedata something = $_POST["whatever"] AND somethingelse = 'whatever');
}
}
elseif(!isset($_POST["house_type"])) {
if($_POST["something"] == 0) {
$search_select = #mysql_query("SELECT * FROM housedata WHERE something = $_POST["whatever"]);
}
elseif($_POST["something"] != 0) {
$search_select = #mysql_query("SELECT * FROM housedata something = $_POST["whatever"] AND somethingelse = 'whatever');
}
}
Now imagine I had like 10 or 20 different select boxes, input fields and checkboxes and I would have to do a mysql query depending on what of these boxes and fiels and checkboxes is filled. This would be a code that is extremely complicated, slow and horrible. So is there a possibility to make a mysql query like:
SELECT * FROM whatever WHERE house_data = '".$whatever."' AND (if(isset($_POST["something"])) { whatever = '".$whatever2."' } AND ...;
You get what I mean? Its a bit complicated to explain but actually its a very important question and probably easy to answer.
Thank you for your help!
phpheini
Generate the WHERE clause prior to running the SQL.
A short example:
$whereClause = "";
if ($_POST['opt1']) {
$opt1 = mysql_real_escape_string($_POST['opt1']);
$whereClause .= "AND opt1='$opt1'";
}
if ($_POST['opt2']) {
$opt2 = mysql_real_escape_string($_POST['opt2']);
$whereClause .= "AND opt2='$opt2'";
}
mysql_query("SELECT * FROM table WHERE 1 ".$whereClause);
To point you a little bit into the right direction, try something like this:
if(isset($_POST["something"]))
{
$where = " AND whatever = '".$whatever2."'";
}
else $where = '';
mysql_query("SELECT * FROM whatever WHERE house_data = '".$whatever."'".$where);
$where = array();
if($_POST["something"]) {
$where[] = " something =".$_POST["something"];
}
if($_POST["something2"]) {
$where[] = " something2=".$_POST["something2"];
}
.
.
.
//build where string
$where_ = !(empty($where) ? " WHERE ".implode(" AND ",$where) : "";
//build sql
$sql = "SELECT * ... ".$where;
write some simple query builder
$where = array();
if($_POST["something"]) {
$where[] = sprintf(" something='%s'",$_POST["something"]);
//sprintf - prevent SQL injection
}
if($_POST["something2"]) {
$where[] = sprintf(" something2='%s'",$_POST["something2"]);
}
//build where string
$where_str = " WHERE ".implode(" AND ",$where);
//build sql
$sql = "SELECT * ... $where_str";
You need to build your search string separately but the format is simply
SELECT * FROM your_table WHERE number = {$number} AND sentence = '{$sentence}';
Since you are creating the search term based on PHP logic do this:
$search = "SELECT * FROM your_table WHERE ";
if(isset($whatever)) $search .= "something = '{$whatever}'";
if(isset($whateverelse)) $search .= " AND somethingelse = '{$whateverelse}'";
$search_select = mysql_query($search);

Categories