Reputation: 1773
So I have a database table with the following columns:
ID
Foo
Bar
Gux
Foo can hold the values [a, b, c], Bar [1, 2, 3], and Gux [x, y, z].
In my interface I have a HTML select box to filter on Foo, Bar, and Gux. The problem is that the user can filter on one, two, or three parameters in random order.
This gives me a problem to make an efficient SQL-query and bind_param.
I could do something like this:
//Pseudo code
$sql = "";
if (isset($_GET['foo'])) {
$sql = "SELECT * FROM ... WHERE foo=?";
}
if (isset($_GET['bar'])) {
$sql = "SELECT * FROM ... WHERE bar=?";
}
if (isset($_GET['gux'])) {
$sql = "SELECT * FROM ... WHERE gux=?";
}
But what if the use selected foo and bar? This would also be very ugly and hard to implement the bind_params too.
Ideal would be a wildcard so I could do
//Pseudo code
$sql = "SELECT * FROM ... WHERE foo=* AND bar=* AND gux=*";
and only replace the *
with an actual value when a filter for that column is selected. But this is not supported for integers.
Another option I thought of would be to do the following:
//Pseudo code
$sql = "SELECT * FROM ... WHERE foo=filter1 OR bar=filter2 OR gux=filter3";
And to programmatically replace the OR
with AND
when a value for that column is selected. This also would solve the bind_param issue. But I don't know if this is the best way to do it.
Upvotes: 0
Views: 686
Reputation: 57121
As RiggsFolly has mentioned, build the WHERE clause dynamically. This code assumes there will be at least 1 option (otherwise add the WHERE conditionally as well.)
Each part is added to a list along with a corresponding bind array, this shows the data, you will need to add the actual API part for the database.
The WHERE part is put together using implode()
with AND
as the glue...
$binds = [];
$where = [];
$types = '';
if (isset($_GET['foo'])) {
$where[] = "foo=?";
$binds[] = $_GET['foo'];
$types .= "s";
}
if (isset($_GET['bar'])) {
$where[] = "bar=?";
$binds[] = $_GET['bar'];
$types .= "s";
}
if (isset($_GET['gux'])) {
$where[] = "gux=?";
$binds[] = $_GET['gux'];
$types .= "i";
}
$sql = "SELECT * FROM ... WHERE " . implode(" AND ", $where);
echo $sql.PHP_EOL;
print_r($binds);
with 1 in the foo value gives...
SELECT * FROM ... WHERE foo=?
Array
(
[0] => 1
)
Then use the types and the binds in the bind_param()
...
bind_param($types, ...$binds);
Upvotes: 2