Building MySQL query based on posted variables - php

This seems like such a simple task, but I'm having a hard time finding a solution that I like for this. I can't find anything I would consider anything other than clunky. Here's what I'm working with:
There is a search form that posts variables to the processing script. These variables are the filters for the data being queried. Depending on the rights of the user, there may be more or less variables coming in, depending on the filters they have access to. Each filter refers to a field in the table the results are coming from, basically. One option for each filter is "ANY" as well, so no WHERE clause is needed.
What's a good way to build the query string. Let's say there's four variables coming back: $firstname, $lastname, $age, $dob. But only some users have access to filter by $age and $dob.
$query = "SELECT * FROM people";
if(($firstname != 'ANY' && !empty($firstname)) ||
($lastname != 'ANY' && !empty($lastname)) ||
($age != 'ANY' && !empty($age)) ||
($dob != 'ANY' && !empty($dob))) {
$query .= " WHERE";
}
if($firstname != 'ANY' && !empty($firstname)) {
$query .= " firstname='$firstname'";
}
if($lastname != 'ANY' && !empty($lastname)) {
if($firstname != 'ANY' || !empty($firstname)) {
$query .= " AND";
}
$query .= " lastname='$lastname'";
}
...
And so on. But that just looks dumb, horrible, and ridiculously inefficient to me. I'm using a slightly modified MVC pattern, so would it make sense to build out methods in the search model for each possible filter?

I'd go for this:
$query = "SELECT * FROM people";
$whereClause = " WHERE 1 = 1 ";
if($firstname != 'ANY' && !empty($firstname)) {
$whereClause .= " AND firstname='$firstname' ";
}
if($lastname != 'ANY' && !empty($lastname)) {
$whereClause .= " AND lastname='$lastname' ";
}
$query .= $whereClause;
You could alternatively collect all statements into an array and just go:
if (count($arr)>0) {
$query = "$query
WHERE ". implode(" AND ",$arr);
}

You can extend this:
http://code.google.com/p/mysql-query-builder/

here's some code that will pull all posted variables and string them together.
foreach($_POST as $name=>$value){
$arrFields[] = $name." = '".$value."'";
}
$sSql = "SELECT * FROM people WHERE 1 AND ".implode(" AND ",$arrFields);
OR if your field names are not the same as your table names, or if you want to treat the fields differently in your SQL, you can use a switch.
foreach($_POST as $name=>$value){
switch($name){
case "firstname":
$arrFields[] = "fName = '".$value."'";
break;
case "lastname":
$arrFields[] = "lName = '".$value."'";
break;
case "age":
$arrFields[] = "bioAge >= ".$value;
break;
}
}
$sSql = "SELECT * FROM people WHERE 1 AND ".implode(" AND ",$arrFields);

Related

PHP mysql Query Builder that displays just what I want

I'm relatively new to PHP and I need some help on a search query.
I have a few drop down 'select' and a 'checkbox group' which will filter the search from database using (...WHERE somethingA = 'somethingA' && somethingB = 'somethingB' etc)
That's all working great but the problem comes when I want to make it so that some search fields DONT have to be used, so if 'SomethingA' is either disabled or value='none' then it will only return WHERE somethingB = 'SomethingB'.
I have tried using OR instead of AND but that returns both values if they are true and not really filtering it properly.
my initial solution was to have if..else statements to define the query,
for example:
$query = "SELECT * FROM table";
$results = $con->query("$query $where $QueryA $QueryB $QueryC");
if($_GET['SomethingA'] == "none" && $_GET['SomethingB'] == "none" && $_GET['SomethingC'] == "none"){
$where = ""
$QueryA = ""
$QueryB = ""
$QueryC = "ORDER by ID" //if all search field is 'none' then get all results
}elseif($_GET['SomethingB'] == "none" && $_GET['SomethingC'] == "none"){
$where = "WHERE"
$QueryA = "SomethingA = '{SomethingA}'" //only use A filter one field
$QueryB = ""
$QueryC = ""
}elseif($_GET['SomethingA'] == "none" && $_GET['SomethingC'] == "none"){
$where = "WHERE"
$QueryA = ""
$QueryB = "SomethingB = '{SomethingB}'" //only use B filter one field
$QueryC = ""
.....
it works but you can already see the problem as if i wanted to cross matrix all conditions it becomes very lengthy and confusing.
So my question is whether there is a much better way of doing this, for instance, make value='none' return all results?
been looking around and attacking it from many angles but cant find a solution..
maybe javascript could help but im not the best with it.
thanks in advance
The question is not too clear but look into this. It should help.
$query="SELECT * FROM table WHERE";
$query_link = " AND ";
$isASet=false;
$isBSet=false;
$isCSet=false;
if(strcmp($_GET['SomethingA'],"none") != 0){
$query.=" column = {$_GET['SomethingA']}";
//set this to true for later if statements
$isASet=true;
}
if(strcmp($_GET['SomethingB'],"none") != 0){
//check if A has been set, if yes include an AND
if($isASet){
$query.=$query_link;
}
//include this one as usual
$query.=" column = {$_GET['SomethingB']}";
$isBSet=true;
}
if(strcmp($_GET['SomethingC'],"none") != 0){
//check if A or B has been set, if yes include an AND
if($isASet || $isBSet){
$query.=$query_link;
}
//include this as usual
$query.=" column = {$_GET['SomethingC']}";
}
//run query and collect result
$result = $connection->query($query);

Building a Dynamic MySQL Query Based on Multiple Variables and Conditions

I am hoping this title represents this question well. I am attempting to build a dynamic query based on multiple $vars existing. I am attempting to make this work using a simple if/ifelse/else block but can't seem to get it to work correctly. The first if statements execute accordingly but the third fails. I am new to PHP so I am assuming this a beginner mistake. I also believe there is most likely a far more eloquent way to achieve the desired results.
Basically the user enters a few inputs into multiple text fields. Only one field, out of the 3 needs to contain a value, but 2 or all 3 can as well. If the value does not exist in a field it should generate a Query based on the values provided. I am validating and a creating a variable for each input than checking to see if those variables contain a value or exist.
//////////////////////////////////////////////////////
if(isset($_POST['inputName']) && $_POST['inputName'] != ""){
$inputName = preg_replace('#[^a-z 0-9?!]#i', '', $_POST['inputName']);
}
if(isset($_POST['inputState']) && $_POST['inputState'] != ""){
$inputState = preg_replace('#[^a-z 0-9?!]#i', '', $_POST['inputState']);
}
if(isset($_POST['inputCost']) && $_POST['inputCost'] != ""){
$inputCost = preg_replace('#[0-9]#i', '', $_POST['inputCost']);
}
///////////////////////////////////////////////////////
if (!empty($inputName) AND !empty($inputState) AND !empty($inputCost)){
$sqlCommand = "SELECT * FROM hciproject WHERE school_name LIKE '%$inputName%' AND school_state LIKE '%$inputState%' AND school_cost < '$inputCost'";
}
elseif (!empty($inputName) AND !empty($inputState)){
$sqlCommand = "SELECT * FROM hciproject WHERE school_name LIKE '%$inputName%' AND school_state LIKE '%$inputState%'";
}
elseif (!empty($inputName) AND !empty($inputCost)){
$sqlCommand = "SELECT * FROM hciproject WHERE school_name LIKE '%$inputName%' AND school_cost < '$inputCost'";
}
elseif (!empty($inputState) AND !empty($inputCost)){
$sqlCommand = "SELECT * FROM hciproject WHERE school_state LIKE '%$inputState%' AND school_cost < '$inputCost'";
}
else{
$searchOut .= "0 Results Found";
}
// Connect to DB
include_once("database_connection.php");
$query = mysql_query($sqlCommand) or die(mysql_error());
$count = mysql_num_rows($query);
///////////////////////////////////////////////////////
Additionally I was going to create elseif statements containing only one variable.
Any help with this would be greatly appreciated.
try this:
$inputName = preg_replace('#[^a-z 0-9?!]#i', '',& $_POST['inputName']);
$inputState = preg_replace('#[^a-z 0-9?!]#i', '',& $_POST['inputState']);
$inputCost = preg_replace('#[0-9]#i', '',& $_POST['inputCost']);
$selectCondition = 1;
if($inputName) $selectCondition.= " and school_name LIKE '%$inputName%' ";
if($inputState ) $selectCondition.= " and school_state LIKE '%$inputState%' ";
if($inputCost ) $selectCondition.= " and school_cost < $inputCos ";
Important:
& $_POST['inputName'] is equal to (isset($_POST['inputName']) && $_POST['inputName'] != "")

php mysql multiple field search empty fields

<?php
if(isset($_POST['submit'])) {
$fields = array('field1', 'field2', 'field3');
$conditions = array();
foreach($fields as $field){
if(isset($_POST[$field]) && $_POST[$field] != '') {
$conditions[] = "`".$field."` like '%" . mysql_real_escape_string($_POST[$field]) . "%'";
}
}
$query = "SELECT * FROM customer ";
if(count($conditions) > 0) {
$query .= "WHERE " . implode (' AND ', $conditions);
}
$result = mysql_query($query);
$say = mysql_num_rows($result);
if ($say == 0) {
echo "<tr>no result.</tr>";
} else {
echo '...';
while($row = mysql_fetch_array($result))
{
...
}}
} ?>
Why doesn't this code checking empty fields? It returns results that has empty field even form submits empty.
The only improvement I think of is trim():
if(isset($_POST[$field]) && trim($_POST[$field]) != '') {
however, I am sure it is not the issue.
Have you ever thought of printing the resulting query out?
Look, you're writing a program to create some string (SQL query). But for some reason never interested in this program's direct result, judging it by some indirect results. May be it's data/query logic makes such results, but the query itself is okay?
if the query is still wrong - continue debugging.
Echo everything involved - print variables, condition results, intermediate results in the loop - and look for inconsistencies
$query = "SELECT * FROM customer ";
if(count($conditions) > 0) {
$query .= "WHERE " . implode (' AND ', $conditions);
}
When form is submitted empty ($conditions=0) it returns all table (select * from customer).
Added an else condition and fixed. Thanks for print query advices.
For checking something is empty or not. You can use empty() method.
Check this:
empty()
isset() only check whether that object/variable is set or not. For more details check this
isset()

Dynamic OR/AND in query

Based on user selections, I need to filter results in my query, but I'm stuck on how to correctly implement dynamic OR statements after my AND. I'm currently using Active Record in CodeIgniter, but this may have to change.
I essentially need to create the following snippet: "WHERE city.id = 9 AND (eventType = 8 or eventType = 9)"
if there are no OR statements, then I don't need the AND
there could be 1-n OR statements
My code currently is as follows:
$this->db->where('city.id =', $cityID);
if ($eventTypes != NULL){
foreach ($eventTypes as $item){
$eventTypeID = intval($item);
$this->db->or_where('eventtype.id =', $eventTypeID);
}
}
This produces: WHERE city.id = 13 OR eventtype.id = 6 OR eventtype.id = 8 ... so I need the AND (
Codeigniter's "ActiveRecord" (airquotes...) Class is fairly limited and doesn't do well with more advanced AND/OR scoping, and points you back to raw sql for "more advanced" queries.
I would formulate your own WHERE string to build the specific query you are wanting and then just use
$this->db->where($sql)
example...
$where = "city.id = $cityID ";
if ($eventTypes != NULL)
{
$where .= "AND ( ";
foreach ($eventTypes as $i => $type)
{
$eventTypeID = intval($type);
// if it's not the first element
// (assumes $eventTypes is non-associative)
if ($i !== 0)
{
$where .= "OR ";
}
$where .= "eventtype.id = $eventTypeID ";
}
$where .= " ) ";
}
$this->db->where($where);

elseif not working

This doesn't make sense.. I'm trying to sort posts according to the value of a URL parameter but my elseif statement isn't working.
This is a function that adds another WHERE clause to the query. There are no MYSQL errors I'm just having statement trouble.
function sort_where($where)
{
if (isset($_GET['sort'])) {
$sort = $_GET['sort'];
if ($sort = "up") {
$where .= " AND $sort > 1";
}
elseif ($sort = "down") {
$where .= " AND $sort > 1";
}
}
return $where;
}
The query eventually looks like this
$query = "SELECT * FROM posts WHERE something = $something AND $sort > 1";
The if statement works, the elseif is ignored. I get posts with up > 1 regardless or vice-versa if $sort = down in the if statement.
Actually, neither of the two inner ifs are working correctly.
You need to use == not =. One equals sign means assignment, and if you assign to a truthy value it always evaluates to true in an if condition. That's why your elseif appears to never happen.
You may also need to fix your WHERE clauses, they don't make sense to me (you're sorting but comparing to an up column and a down column?). Or maybe that's how you designed your table...
Based on your comments, try the following SQL WHERE clauses and see if you get the correct posts:
if ($sort == "up") {
$where .= " AND up > down";
}
elseif ($sort == "down") {
$where .= " AND down > up";
}
Single = means variable 1 = variable 2
Double == means compare
Also if you are going to use this code make sure you put mysql_real_escape_string() around your $_GET statements or anything that has user inputs or people will be able to use sql injection.
E.g. mysql_real_escape_string($_GET['sort']) and if you are using it multiple times makes sure you use a variable
Here is the corrected code ;)
function sort_where($where)
{
if (isset($_GET['sort'])) {
$sort = $_GET['sort'];
if ($sort == "up") {
$where .= " AND $sort > 1";
}
elseif ($sort == "down") {
$where .= " AND $sort > 1";
}
}
return $where;
}
Two problems:
if ($sort = "up") {
= is the assignment operator. You need to use == here if you want to test for equality.
Also, the body of both conditionals:
if ($sort = "up") {
$where .= " AND $sort > 1";
}
elseif ($sort = "down") {
$where .= " AND $sort > 1";
}
Are identical. I don't think you mean to append the same basic string to the query, do you? (Granted $sort will be different in either case, but why not just hardcode the strings in if that's what you mean anyway. This just reads really confusing, and it's hard to tell exactly what your intent is.)
if ($sort = "up")
elseif ($sort = "down")
should be
if ($sort == "up")
elseif ($sort == "down")

Categories