PHP Ternary Operator with Dates to MS SQL Server - php

I'm doing a basic sql string builder, and I'm trying to use ternary operators to conditionally feed a null value, or the value of the datetime into the statement.
Basic syntax of the update statement if all values are present.
UPDATE tblRecvLog
SET ScheduledTime = 'datetime',
ScaleInTime = 'datetime',
SampleToLabTime = 'datetime',
ScaleWeight = 'weight',
SealTop = 'sealnumber',
SealBottom = 'sealnumber'
WHERE pkRecvLogID = 'uniqueid';
I'm receiving these values from an ajax post, and they're valid values in my $_POST data, all of the encoding and decoding being done appropriately. When a datetime is not specified on the form and the user submits an update to the table record, I want to write a null value to the database. I'm trying to properly use ternary operator in my sql string builder to make this work.
$sql = "UPDATE tblRecvLog SET "
. ($ScheduledTime == '') ? "ScheduledTime = NULL," : "ScheduledTime = '{$ScheduledTime}',"
. ($ScaleInTime == '') ? "ScaleInTime = NULL," : "ScaleInTime = '{$ScaleInTime}',"
. ($SampleToLabTime == '') ? "SampleToLabTime = NULL," : "SampleToLabTime = '{$SampleToLabTime}',"
. "ScaleWeight = '{$ScaleWeight}',
SealTop = '{$SealTop}',
SealBottom = '{$SealBottom}'
WHERE pkRecvLogID = '{$pkRecvLogID}'";
The part I'm not wrapping my head around:
Dates need to be wrapped in '' for SQL server.
My use of ' and " is making it confusing.

I like to use vsprintf for this sort of thing, I think it makes things nicer to read. You can read more about the format specifiers. In this example I am just using %s to represent strings.
<?php
$query = "
UPDATE
tblRecvLog
SET
ScheduledTime = %s,
ScaleInTime = %s,
SampleToLabTime = %s,
ScaleWeight = '%s',
SealTop = '%s',
SealBottom = '%s'
WHERE
pkRecvLogID = '%s';";
$values = [
($ScheduledTime == '') ? NULL : "'" . $ScheduledTime . "'",
($ScaleInTime == '') ? NULL : "'" . $ScaleInTime . "'",
($SampleToLabTime = '') ? NULL : "'" . $SampleToLabTime . "'",
$ScaleWeight,
$SealTop,
$SealBottom,
$pkRecvLogID,
];
$sql = vsprintf($query, $values);

Another variant:
$vars = array(
"ScheduledTime" => $ScheduledTime,
"ScaleInTime" => $ScaleInTime,
"SampleToLabTime" => $SampleToLabTime,
"ScaleWeight" => $ScaleWeight
"SealTop" => $SealTop,
"SealBottom" => $SealBottom
);
$set = array();
foreach($vars as $k => $v)
{
if ($v == '' || is_null($v))
{
$set[] = sprintf("`%s` = NULL", $k);
} else {
$set[] = sprintf("`%s` = '%s'", $k, $v);
}
}
$set = implode(', ', $set);
if ($set != "")
{
$sql = sprintf("UPDATE `tblRecvLog` SET %s WHERE `pkRecvLogID` = '%s'", $set, $pkRecvLogID);
...
}

Related

Multiple variables in prepared statement PHP

I'm having an issue preparing a SQL statement:
$statement = $conexion->prepare(
'SELECT * FROM celulares
WHERE (MARCA = :marca )
AND
(CATEGORIA = :categoria1 OR CATEGORIA = :categoria2 OR CATEGORIA = :categoria3)
AND
(CATEGORIA2 = :categoria1 OR CATEGORIA2 = :categoria2 OR CATEGORIA2= :categoria3)
AND
(CATEGORIA3 = :categoria1 OR CATEGORIA3 = :categoria2 OR CATEGORIA3 = :categoria3)');
Giving placeholders values with this:
$statement->execute(array(':categoria1' => $categoria1,
':categoria2' => $categoria2,
':categoria3' => $categoria3,
':marca' => $query
));
$query value may variate when my application begins depending on some results:
if ($entrada == "LG") {
if ($query == "") {
$query = "LG";
} else {
$query = $query . ' OR MARCA = "LG" ';
}
}
if ($entrada == "APPLE") {
if ($query == "") {
$query = "APPLE";
} else {
$query = $query . ' OR MARCA = "APPLE" ';
}
}
if ($entrada == "HUAWEI") {
if ($query == "") {
$query = "HUAWEI";
} else {
$query = $query . ' OR MARCA = "HUAWEI" ';
}
}
I tried a lot of things, but none of those worked out it returns an empty array, the only one who works was changing this line of my prepared statement:
WHERE (MARCA = :marca OR MARCA = :marca2 OR MARCA = :marca3 )
And as many "MARCA" as results, i think it's not the best way to do it
UPDATED:
Now trying with IN Statement in my Query (Thanks you all for helping me)
Now it looks like:
$marcas = array("LG", "HUAWEI"); (Static values for test)
$inQuery = implode(',', array_fill(0, count($marcas), '?'));
$statement = $conexion->prepare(
'SELECT * FROM celulares
WHERE (MARCA = IN (' . $inQuery . '))
AND
(CATEGORIA = :categoria1 OR CATEGORIA = :categoria2 OR CATEGORIA = :categoria3)
AND
(CATEGORIA2 = :categoria1 OR CATEGORIA2 = :categoria2 OR CATEGORIA2= :categoria3)
AND
(CATEGORIA3 = :categoria1 OR CATEGORIA3 = :categoria2 OR CATEGORIA3 = :categoria3)');
foreach ($marcas as $k => $marca) {
$statement->bindValue(($k+1), $marca);
}
$statement->bindValue(':categoria1', $categoria1);
$statement->bindValue(':categoria2', $categoria2);
$statement->bindValue(':categoria3', $categoria3);
$statement->execute();
Getting: Warning: PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: mixed named and positional parameters
Trying to fix it
You can simplify your query:
SELECT * FROM celulares
WHERE (MARCA = :marca )
AND (:categoria1,:categoria2,:categoria3)
IN (
(CATEGORIA,CATEGORIA2,CATEGORIA3),
(CATEGORIA,CATEGORIA3,CATEGORIA2),
(CATEGORIA2,CATEGORIA,CATEGORIA3),
(CATEGORIA2,CATEGORIA3,CATEGORIA),
(CATEGORIA3,CATEGORIA,CATEGORIA2),
(CATEGORIA3,CATEGORIA2,CATEGORIA)
)
This way you only pass in the categories once, and compare it against the six possible permutations of three categories.
That being said, this is a sign that your database is in very poor shape. Generally speaking having any kind of "column2", "column3" system is a sign that you need to restructure your database - the kind of queries you end up with, like the above, are only going to get worse.
Specifically, in this case, just adding CATEGORIEA4 would increase the amount of permutations you need to define from 6 to 24!!
EDIT: I completely missed the part about :marca and IN - I was too focussed on the bad state of the database with regard to categories, sorry!
Well, i fix it, probably it's not the best way to solve it but i have this now:
I fill array with entries from POST
$query = array();
$index = 0;
foreach ($_POST as $entrada) {
switch($entrada) {
case "SAMSUNG":
$query[] = "SAMSUNG";
break;
case "LG":
$query[] = "LG";
break;
case "APPLE":
$query[] = "APPLE";
break;
case "HUAWEI":
$query[] = "HUAWEI";
break;
}
}
$inQuery = str_repeat('?,', count($query) - 1) . '?';
Here's my new query: Problem was that i was mixing "?" with placeholders (:) which not is recommended
$statement = $conexion->prepare(
"SELECT * FROM celulares
WHERE ( MARCA IN($inQuery))
AND
(CATEGORIA = ? OR CATEGORIA = ? OR CATEGORIA = ?)
AND
(CATEGORIA2 = ? OR CATEGORIA2 = ? OR CATEGORIA2= ?)
AND
(CATEGORIA3 = ? OR CATEGORIA3 = ? OR CATEGORIA3 = ?)");
Then i bindValues like that
$c = 0;
foreach ($query as $q => $queries) {
$c++;
$statement->bindValue(($q+1), $queries);
}
$statement->bindValue($c+1, $categoria1);
$statement->bindValue($c+2, $categoria2);
$statement->bindValue($c+3, $categoria3);
$statement->bindValue($c+4, $categoria1);
$statement->bindValue($c+5, $categoria2);
$statement->bindValue($c+6, $categoria3);
$statement->bindValue($c+7, $categoria1);
$statement->bindValue($c+8, $categoria2);
$statement->bindValue($c+9, $categoria3);
$statement->execute();
$resultados = $statement->fetchAll();
I did many test with a lot of querys and it's working fine, probably it's a "dirty" solution but i'll continue learning
Thanks u all for helping me!

How do I add dynamic WHERE clause for search filtering?

I have 7 search parameters although the code below shows only two, Title and Type.
We would like to give our users the ability to search by ANY of the 7 parameters.
They should also be given the ability to search by more than one parameter.
How would I adapt the code below to use a dynamic $where clause?
Example, a user could select where type='some value'.
A user should also be able to select where type='some value' and title='some value'.
Thank you in advance.
function ms_escape_string($data) {
if ( !isset($data) or empty($data) ) return '';
if ( is_numeric($data) ) return $data;
$non_displayables = array(
'/%0[0-8bcef]/', // url encoded 00-08, 11, 12, 14, 15
'/%1[0-9a-f]/', // url encoded 16-31
'/[\x00-\x08]/', // 00-08
'/\x0b/', // 11
'/\x0c/', // 12
'/[\x0e-\x1f]/' // 14-31
);
foreach ( $non_displayables as $regex )
$data = preg_replace( $regex, '', $data );
$data = str_replace("'", "''", $data );
return $data;
}
$strprojectTitle = null;
$strbidType = null;
if(isset($_POST["projectTitle"]))
{
$strprojectTitle = $_POST["projectTitle"];
}
if(isset($_POST["BidType"]))
{
$strbidType = $_POST["BidType"];
}
?>
<?php
$sql = "Select b.ID,convert(char(10),b.BidDate,101) BidDate,convert(char(10),
b.DueDate,101)DueDate,b.BidTitle,b.DueTime,b.BidID,BidIDFile,
d.Department,b.BidType,CASE WHEN b.AwardDate ='01/01/1900' Then NULL ELSe convert(char(10),b.AwardDate,101)END AS AwardDate,
convert(char(10),b.LastUpdate,101) LastUpdate,s.Status
FROM bids b inner join dept d on b.Department=d.DeptID inner join Status s on b.BidStatus=s.StatusId WHERE b.BidTitle = ' . ms_escape_string($strprojectTitle) . ' OR b.BidType = ' . ms_escape_string($strbidType) . ' ";
///****Latest attempt
$fields = array(
'projectTitle' => 'b.BidTitle',
'BidType' => 'b.BidType'
);
$where = array();
foreach($fields as $fieldPost => $fieldDb) {
if(isset($_POST[$fieldPost]) && strlen($_POST[$fieldPost]) > 0) {
$where[] = "`$fieldDb` = '$_POST[$fieldPost]'";
}
}
$sql = "Select b.ID,convert(char(10),b.BidDate,101) BidDate,convert(char(10),
b.DueDate,101)DueDate,b.BidTitle,b.DueTime,b.BidID,BidIDFile,
d.Department,b.BidType,CASE WHEN b.AwardDate ='01/01/1900' Then NULL ELSe convert(char(10),b.AwardDate,101)END AS AwardDate,
convert(char(10),b.LastUpdate,101) LastUpdate,s.Status
FROM bids b inner join dept d on b.Department=d.DeptID inner join Status s on b.BidStatus=s.StatusId
" . ( count($where) > 0 ? " WHERE " . implode(' AND ', $where) : "" );
Remove this part in your code:
$strprojectTitle = null;
$strbidType = null;
if(isset($_POST["projectTitle"]))
{
$strprojectTitle = $_POST["projectTitle"];
}
if(isset($_POST["BidType"]))
{
$strbidType = $_POST["BidType"];
}
And replace it with the one below, which enables a dynamic way of building the WHERE conditions:
## easily add here the fields you have
$fields = array(
'projectTitle' => 'b.BidTitle',
'BidType' => 'b.BidType'
);
$where = array();
foreach($fields as $fieldPost => $fieldDb) {
if(isset($_POST[$fieldPost]) && strlen($_POST[$fieldPost]) > 0) {
$where[] = "`$fieldDb` = '" . ms_escape_string($_POST[$fieldPost]) . "'";
}
}
## Use the $where array in your final SQL query
## important to test if count($where) > 0 in case no search has been made
$sql = "SELECT ..... " . ( count($where) > 0 ? " WHERE " . implode(' AND ', $where) : "" );
A more advanced example to build the WHERE string by supporting multiple search types (for example the search comparators: LIKE %..% and =)
## support multiple search comparators
$fields = array(
'projectTitle' => array('field' => 'b.BidTitle', 'searchType' => 'like'),
'BidType' => array('field' => 'b.BidType', 'searchType' => 'equal')
);
$where = array();
foreach($fields as $fieldPost => $field) {
if(isset($_POST[$fieldPost]) && strlen($_POST[$fieldPost]) > 0) {
if($field['searchType'] == 'like') {
$where[] = "`".$field['field']."` LIKE '%" . ms_escape_string($_POST[$fieldPost]) . "%'";
} else {
$where[] = "`".$field['field']."` = '" . ms_escape_string($_POST[$fieldPost]) . "'";
}
}
}

remove quotes in post values based on array key name

I want to be able to remove quotations from a field on or abouts the name of 'quote'. On post, all my field names and values get matched up and put into an array then enter to the database. Before the SQL is built and after I build the value-key array, how can I single out the field quote, remove the quotation marks that the user inputted, and then add/keep the content in the $values array for my SQL? The questionable area starts with the comment "remove quotes"
public function insertIntoDb($table, $carryUrl = NULL, $ext = '')
{
if (in_array($table, $this->disallow_insert)) {
self::show_error("Inserting into the table '{$table}' is not possible, check the configuration file if this is an error.");
} elseif (!isset($table)) {
self::show_error('Missing `table` parameter in ' . __FUNCTION__);
}
$resultInsert = Nemesis::query("SHOW COLUMNS FROM {$table}");
if (!$resultInsert) {
self::show_error(QUERY_ERROR);
}
$fieldnames = array();
if ($resultInsert->num_rows > 0) {
while ($row = $resultInsert->fetch_array()) {
$fieldnames[] = $row['Field'];
$values = array_intersect_key($_POST, array_flip($fieldnames));
// $values = array_filter($values, function($x) { return $x !== ''; });
// <5.3 $values = array_filter($values, create_function('$x', 'return $x !== "";'));
}
}
// remove quotes for testimonials
if (array_key_exists('quote', array_change_key_case($values, CASE_LOWER))) {
$values['quote'] = preg_replace("/<!--.*?-->/", "", $values); // remove quotes
}
// filter the array
$values = self::filter($values);
$sql = sprintf("INSERT INTO %s (created, created_by, %s) VALUES (NOW(), '$_SESSION[user_id]', '%s')", $table, implode(', ', array_keys($values)), implode("', '", $values));
if ($this->debug) {
echo '<p>' . $sql . '</p>';
} elseif (Nemesis::query($sql)) {
$msg = new Messages();
$msg->add('s', QUERY_INSERT_SUCCESS);
if ($table == 'projects') {
$msg = new Messages();
$msg->add('s', "Information was added to the database. Time to add images!");
}
if (!is_null($carryUrl) && isset($carryUrl)) {
redirect($carryUrl . '?id=' . $_POST['id'] . '&table=' . $table . $ext);
}
} else {
self::show_error(QUERY_ERROR);
}
}
preg_replace is a function that returns a value, not a void. You'll need to assign the returned value back to $values['quote']:
// remove quotes for testimonials
if (array_key_exists('quote', array_change_key_case($values, CASE_LOWER))) {
$values['quote'] = preg_replace("/(\"|')/", "", $values['quote']); // remove quotes
}

MySQL Search from Multiple User supplied where clause - Fix and Better Algorithm

I want to run search query where i have multiple where clause. and multiple depends upon the user argument.
for example i mean, Search may depend on 1 column, 2 column, 3 column or 6 column in my case, and i don't want to run if-elseif-else statement with all column probability. So, i have just built up below function, but i am stuck with and that comes in between multiple column search case. Below is my code :-
function listPlayer($player="player_guest", $group="group_guest",
$weapon="weapon_guest", $point="point_guest", $power="level_guest",
$status="status_guest") {
$lePlayer = (isset($player) && $player != "player_guest") ?
'player= '.$mysqli->real_escape_string($player).' and' : '';
$leGroup = (isset($group) && $group != "group_guest") ?
'group= '.$mysqli->real_escape_string($group).' and' : '';
$leWeapon = (isset($weapon) && $weapon != "weapon_guest") ?
'weapon= '.$mysqli->real_escape_string($weapon).' and' : '';
$lePoint = (isset($point) && $point != "point_guest") ?
'point= '.$mysqli->real_escape_string($point).' and' : '';
$lePower = (isset($power) && $power != "level_guest") ?
'level= '.$mysqli->real_escape_string($power).' and' : '';
$leStatus = (isset($status) && $status != "status_guest") ?
'status= '.$mysqli->real_escape_string($status).' and' : '';
$query = "Select pid, name from game where {$lePlayer} {$leGroup} {$leWeapon} {$lePoint} {$lePower} {$leStatus} ";
$runQuery = $mysqli->query($query);
}
but problem is and at the end. If i use them, than i have extra and at the end, and if i don't use them that's again an error.
Can some one help me to fix and find better way to do it.
Update: My Update Code that works if some one needs them Thanks to Barmar
function listPlayer($player="player_guest", $group="group_guest",
$weapon="weapon_guest", $point="point_guest", $power="level_guest",
$status="status_guest") {
$lePlayer = (isset($player) && $player != "player_guest") ?
'player= '.$mysqli->real_escape_string($player) : '' ;
$leGroup = (isset($group) && $group != "group_guest") ?
'group= '.$mysqli->real_escape_string($group) : '' ;
$leWeapon = (isset($weapon) && $weapon != "weapon_guest") ?
'weapon= '.$mysqli->real_escape_string($weapon) : '' ;
$lePoint = (isset($point) && $point != "point_guest") ?
'point= '.$mysqli->real_escape_string($point) : '' ;
$lePower = (isset($power) && $power != "level_guest") ?
'level= '.$mysqli->real_escape_string($power) : '' ;
$leStatus = (isset($status) && $status != "status_guest") ?
'status= '.$mysqli->real_escape_string($status) : '' ;
$condition_array = ( $lePlayer , $leGroup , $leWeapon , $lePoint , $lePower , $leStatus)
$condition_stirng = implode(' and ', $condition_array);
$query = "Select pid, name from game where ".$condition_stirng;
$runQuery = $mysqli->query($query);
}
Update:
I got mail from someone at my email which says my code is vulnerable to SQL Injection. Here it is POC http://www.worldofhacker.com/2013/09/interesting-sql-vulnerable-code-even.html
Thanks
Put all the conditions in an array. Then combine them with:
$condition_string = implode(' and ', $condition_array);
The simple solution is to trim the "and" off at the end:
$query = substr($query, 0, strlen($query) - 3);
however a more efficient way would be to put them in a loop, like this:
$wheres = array("player_guest"=>$player, "group_guest"=>$group.....);
$query_where = "";
$i = 0;
foreach($wheres as $where=>$value){
list($condition, $null) = explode("_",$where);
if(isset($value)){
$query_where .= $condition . "='" . $mysqli->real_escape_string($value)."'";
if($i != sizeof($wheres)){
$query_where .= " and ";
}
}
$i++;
}
This is extendable for any number of conditions, and doesnt require the extra string function at the end.
Notice the $defaults is needed to make sure your conditions work. A bit repetitive, but it's all due to your function declaration.
function listPlayer(
$player="player_guest",
$group="group_guest",
$weapon="weapon_guest",
$point="point_guest",
$power="level_guest",
$status="status_guest") {
//I'm just copying whatever is in the default parameters ;)
$defaults = array(
'player' => 'player_guest',
'group' => 'group_guest',
'weapon' => 'weapon_guest',
'point' => 'point_guest',
'power' => 'level_guest',
'status' => 'status_guest'
);
//Set all user parameters into an array, easier to loop through
$data = compact(array_flip($defaults));
//Then we build conditions
$conditions = array();
foreach($data as $k => $v) {
if ($defaults[k] !== $v) {
$v = $mysqli->real_escape_string($v);
$conditions[] = "$k='$v'";
}
}
//And build query
$query = "SELECT pid, name FROM game WHERE ".implode(" AND ", $conditions);
$runQuery = $mysqli->query($query);
}
First of all I recommend you to look at PDO when you work with MySQL in PHP.
Such tasks are always simply solved with array maps.
function listPlayer($player = null, $group = null, $weapon = null, $point = null, $power = null, $status = null) {
$defaults = array(
'player' => 'player_guest',
'group' => 'group_guest',
'weapon' => 'weapon_guest',
'point' => 'point_guest',
'status' => 'status_guest',
);
$values = compact(array_keys($defaults));
$filtered = array_filter(array_diff_assoc($values, $defaults)); //firstly filtering out defaults, then - nulls.
$where = '';
foreach($filtered as $column => $value){
if($where){
$where .= ' AND ';
}
$where .= sprintf("`%s` = '%s'", $column, $mysqli->real_escape_string($value));
}
$query = "SELECT pid, name FROM game WHERE $where";
//executing...
}

Handling a bunch of various requests into the database

I currently have a php page that grabs information from a database and produces HTML with data attributes that are filled in by from the MySQL query. The database is going to be used to search, with many different options for searches.
What I need help with is knowing a way so to organize how the many variables are handled. It's a really big mess of code, and even with all the comments I put it gives me a headache trying to figure out how to add another variable to the search.
All the variables, except for the LIMIT to which row and how many results, are optional. So if someone leaves everything except that blank, I still want it to function as well as if they meticulously filled in all the fields.
Here's what I have, with 6 variables.
<?php
$product_size = "(".$_GET['size']." BETWEEN productsizeDOWN AND productsizeUP)"; // This code sets the variable to input into the MySQL string based on the URL
$product_size_check = $_GET['size']; // the _checks check are used to see if the value is or isn't empty using if statements below
$manufacturer = $_GET['manufacturer'];
$product_manufacterer_check = $_GET['manufacturer']; // _check
$product_invisible = "(hideproduct = '".$_GET['invisible']."')"; // Checks if product is hidden
$product_invisible_check = $_GET['invisible']; // _check
$product_instock_check = $_GET['instock']; // _check
$product_limit0 = $_GET['startat']; // This is the first number after LIMIT; the row to start in.
$product_limit1 = $_GET['results']; // This is how many results to load.
$manufacturer_array = explode(",", $manufacturer); // The manufacturer comes in as "Nike,Addidas,Rebok" and is turned into an array
$manufacturer_imploded = implode("' OR productmanufacturer = '", $manufacturer_array); // Puts it back together with "OR productmanufacturer =" between each name.
$product_manufacterer = ("(productmanufacturer = '".$manufacturer_imploded."')"); // formats it so it can be directly inserted into MySQL string with a WHERE in front.
if($product_invisible_check == ""){
$product_invisible = "";
}else{$where = "WHERE ";}; //Useless code that I havn't deleted that I tried to use when I searched the entire database
if($product_size_check == ""){
$product_size = "";
}else{$where = "WHERE ";};
if($product_manufacterer_check == ""){
$product_manufacterer = "";
}else{$where = "WHERE ";};
if($product_instock_check == "N"){
$product_instock = "(stockstatus <= '0' AND donotallowbackorders = 'Y') AND "; // Checks if product is in stock (Allowing backordering OR stock >1)
$where = "WHERE ";
}
elseif($product_instock_check == "Y") {
$product_instock = "(stockstatus > '0' OR donotallowbackorders = 'N') AND ";
$where = "WHERE ";
}
else {
$product_instock = "";
};
$sql="Select * FROM ioa7pd_Products WHERE ".$product_instock.$product_size."AND".$product_manufacterer_and.$product_manufacterer."".$product_invisible." LIMIT ".$product_limit0.", ".$product_limit1; // The end result of it all.
echo $sql;
?>
When the URL is
test.php?size=5&manufacturer=Nike,Addidas,Rebok&invisible=N&instock=Y&startat=0&results=30
the resulting SQL query is
Select * FROM ioa7pd_Products WHERE (stockstatus > '0' OR donotallowbackorders = 'N') AND (5 BETWEEN productsizeDOWN AND productsizeUP)AND(productmanufacturer = 'Nike' OR productmanufacturer = 'Addidas' OR productmanufacturer = 'Rebok')(hideproduct = 'N') LIMIT 0, 30
But I plan to add more options to the search.
My main question is simply: What way can I organize this to make it simple to add more variables? Tiered if statements?
Travesty has been helping me with my code and has really been great in organizing it.
Here is the current code. It needs to be secure to prevent injection.
// Database connection
$con = mysql_connect("[CENSORED]","[CENSORED]","[CENSORED]")
or die("Could not connect: " . mysql_error());
mysql_select_db("[CENSORED]") or die('Could not select database');
// Begin organization of URL variables into MYSQL Query
$get_size = $_GET['size'];
$get_manufacturer = $_GET['manufacturer'];
$get_invisible = $_GET['invisible'];
$get_instock = $_GET['instock'];
$get_sex = $_GET['sex'];
$get_startat = $_GET['startat'];
$get_results = $_GET['results'];
if ($get_size != ""){
$all_selectors[] = "(".$get_size." BETWEEN productsizeDOWN AND productsizeUP)"; // Add to array if size is not blank.
};
if ($get_manufacturer != ""){
$manufacturer_exploded = explode(",", $get_manufacturer);
$manufacturer_imploded = implode("' OR productmanufacturer = '", $manufacturer_exploded);
$all_selectors[] = ("(productmanufacturer = '".$manufacturer_imploded."')");
};
if ($get_invisible != ""){
$all_selectors[] = "(hideproduct = '".$get_invisible."')";
};
if($get_instock == "N" or $get_instock == "n"){
$all_selectors[] = "(stockstatus <= '0' AND donotallowbackorders = 'Y')";
}elseif($get_instock == "Y" or $get_instock == "y") {
$all_selectors[] = "(stockstatus > '0' OR donotallowbackorders = 'N')";
};
if ($get_startat != "" or $get_results != ""){
$number_results = "LIMIT ".$get_startat.", ".$get_results;
} else {
$number_results = "LIMIT 0, 15";
};
// All variables are now in an array, except "startat" and "results"
$all_selectors0 = "WHERE ".implode(" AND ", $all_selectors);
// Create SQL query
$sql="Select * FROM sadsads_Products ".$all_selectors0." ".$number_results;
I would do something more like this. It's not tested and probably not 100% complete...you may need to do some further customization, particularly with adding more special cases to the switch statement, but this will make adding more variables much easier:
REMOVED OLD EXAMPLE, SEE UPDATED EXAMPLE BELOW
One key thing to note is that you aren't sanitizing your database inputs. Your code is vulnerable to SQL injection. My example above helps to solve that, but this code isn't fully tested, so you should ensure that all user input is sanitized before using it in any query.
If your field names don't match up with your MySQL columns (which it looks like they don't), then you can fix them with an associative array:
$columns = array(
// [form field] => [mysql column]
'size' => 'product_size',
'manufacturer' => 'product_manufacturer',
'invisible' => 'hideproduct'
// ...
);
And then in your switch statement, do something more like this:
$whereClause[] = "{$columns[$key]} = '{$value}'";
FINAL UPDATE:
DOCUMENTED SAMPLE - has plenty of comments and extra stuff to make it work on Codepad
EXACT WORKING CODE - you should be able to copy and paste this (and add your DB credentials) and it should work:
$con = mysqli_connect("[CENSORED]", "[CENSORED]", "[CENSORED]") or die("Could not connect: ". mysqli_error());
mysqli_select_db("[CENSORED]") or die("Could not select database");
$columns = array(
'size' => 'product_size',
'manufacturer' => 'product_manufacturer',
'invisible' => 'hideproduct'
);
$whereClause = array();
$limit = array("startat" => 0, "results" => 15);
foreach ($_GET as $key=>$value) {
$key = mysqli_real_escape_string($key);
if (is_array($value)) {
for ($i = 0; $i < count($value); $i++) {
$value[$i] = mysqli_real_escape_string($value[$i]);
}
} else {
$value = mysqli_real_escape_string($value);
}
switch ($key) {
case 'size':
$whereClause[] = "({$value} BETWEEN productsizeDOWN AND productsizeUP)";
break;
case 'startat':
case 'results':
$limit[$key] = $value;
break;
case 'instock':
$whereClause[] = "(stockstatus ". ($value == 'N' ? "<=" : ">") ." '0' ". ($value == 'N' ? "AND" : "OR") ." donotallowbackorders = '". ($value == 'N' ? "Y" : "N") ."')";
break;
default: {
if (is_array($value)) {
$whereClause[] = "{$columns[$key]} IN ('". implode("', '", $value) ."')";
} else {
$whereClause[] = "{$columns[$key]} = '{$value}'";
}
}
}
}
$sql = "SELECT * FROM ioa7pd_Products". (empty($whereClause) ? "" : " WHERE ". implode(" AND ", $whereClause)) ." LIMIT {$limit['startat']}, {$limit['results']}";
echo $sql;
after
else {
$product_instock = "";
};
do:
$limit = '';
if( !empty($product_limit0) && !empty($product_limit1) )
$limit = " LIMIT $product_limit0, $product_limit1";
$sql="Select * FROM ioa7pd_Products WHERE ".$product_instock.$product_size."AND".$product_manufacterer_and.$product_manufacterer."".$product_invisible." $limit"; // The end result of it all.
echo $sql;
If you have separate params in $_GET, you would have to traverse with multiple if statements. you can pass the params as an array into $_GET, with numeric keys, that would help a bunch.

Categories