Reputation: 785
The Aim
Hi, I'm trying to shorten my code by building the query dynamically based on the $_GET
. Current I have every possible If statement with the relevant SELECT
query. However I would like to create a dynamic system for feature updates.
Current Progress
//Set Filter based on url
if ($_GET[GAME] != "") { $gameFilter = $_GET[GAME]; } else { $gameFilter = ''; }
if ($_GET[Region] != "") { $regionFilter = $_GET[Region]; } else { $regionFilter = ''; }
if ($_GET[Console] != "") { $consoleFilter = $_GET[Console]; } else { $consoleFilter = ''; }
$result = get_matchfinder($gameFilter, $regionFilter, $consoleFilter);
//The Function
function get_matchfinder($gameFilter, $regionFilter, $consoleFilter) {
//Set Varibles
$database = 'matchFinder';
$order = 'DESC';
$limit = '20';
//Query Function
$connection = connection();
$sql = 'SELECT * FROM '. $database .' WHERE game = "'.$gameFilter.'" AND region = "'.$regionFilter.'" AND console = "'.$consoleFilter.'" ORDER BY ID '. $order .' LIMIT '. $limit .'';
$response = mysqli_query($connection, $sql);
//Return
return $response;
}
Problem
Currenly it works when all of the filters are active but if one of them isn't the whole query fails, I know thats because it is try to SELECT something matching ''
.
So my questions is how do I make it search for all when that filters is not set?
Upvotes: 0
Views: 79
Reputation: 50612
You should build the query parts depending on the length of the filter:
$sql = '
SELECT * FROM '.$database.'
';
$filters = array();
if (strlen($gameFilter) > 0) {
$filters[] = 'game = "'.mysqli_escape_string($connection, $gameFilter).'"';
}
if (strlen($regionFilter) > 0) {
$filters[] = 'region = "'.mysqli_escape_string($connection, $regionFilter).'"';
}
if (strlen($consoleFilter ) > 0) {
$filters[] = 'console= "'.mysqli_escape_string($connection, $consoleFilter).'"';
}
if (count($filters) > 0) {
$sql .= ' WHERE '.implode(' AND ', $filters);
}
if (strlen($oder) > 0) {
$sql .= ' ORDER BY ID '.$order;
}
if ($limit > 0) {
$sql .= ' LIMIT '.$limit;
}
$response = mysqli_query($connection, $sql);
What you're doing there is building up an array of conditions, based on the length of the condition. If the condition's input is an empty string, it isn't added to the array. At the end, if there are any filters, use implode
to bind the conditions into a string. The way implode
works, if there's only one condition, the glue string isn't used.
It also bears mentioning that you are exposing yourself to SQL injection. The above code shows the use of mysqli_escape_string
to escape the input, but you should look in to parameterized queries to take full precaution: http://php.net/manual/en/mysqli.quickstart.prepared-statements.php -- the above sample would only be slightly different if you used paraterized queries, but significantly more safe.
Documentation
strlen
- http://php.net/manual/en/function.strlen.phpimplode
- http://php.net/manual/en/function.implode.phpUpvotes: 2
Reputation: 4385
You would have to build your search dynamically
You could start your base query with
$sql='SELECT * FROM '. $database .' WHERE 1=1'
Then, if $gameFilter!="", append to your existing $sql string with "and game=$gameFilter"
The syntax for appending would be like this
if ($gameFilter!="")
{
$sql.=' and game=$gameFitler'
}
and so on checking for all of your search conditions.
Upvotes: 2
Reputation: 48207
Make you string like this
$sql = 'SELECT * FROM '. $database .' WHERE 1=1 {0} {1} {2}'
if ( $gameFilter <> '')
$sql = str_replace("{0}", "AND game = '".$gameFilter."'" , $sql);
else
$sql = str_replace("{0}", "" , $sql);
if ( $regionFilter <> '')
$sql = str_replace("{1}", "AND region = '".$regionFilter."'" , $sql);
else
$sql = str_replace("{1}", "" , $sql);
if ( $consoleFilter <> '')
$sql = str_replace("{2}", "AND console = '".$consoleFilter."'" , $sql);
else
$sql = str_replace("{2}", "" , $sql);
Upvotes: 1