Reputation: 519
I have an app that displays a list of files from a database table. I would like the user to be able to create a group by choosing options that will filter the list of files and only show the ones that match. The group options are added to another table for later use.
Here are the options:
name
year
type
room
day
time
All of them apart from name
are optional and can be left blank by the user. Some of the options can contain multiple values seperated by a ,
.
Here is my code to add this information:
if ($addGrp = $m->prepare("SELECT * FROM pro_files WHERE userid=?, name=? ...")) {
$addGrp->bind_param('is ...',$userid, $name ...;
}
For reference, to select these dymanic columns I'll be using:
WHERE room in (g23,f43,g43) AND type in ('pptx,ppt,ai,pdf')
and the variables used to bind them are comma separated values as such (generated based on what the user chooses, the variable won't exist if the user chose nothing):
$room = 'g23,f43,g43';
$type = 'pptx,ppt,ai,pdf';
Using the old MYSQL method I could have just created a query string no problem. How do I create a dynamic query when I also have the bind_param
line to deal with?
For demonstration I've added ...
where I need to dynamically generate the query.
I can't use PDO due because the rest of the app is currently using MYSQLi, the job would be too great.
Alternatively, is it possible to use a wildcard in an IN clause? I could just make '' = '*'
within PHP in that case. However room in ('*')
doesn't work.
Upvotes: 1
Views: 517
Reputation: 157872
Well, with vanilla mysqli prepared statements it would be quite a hard challenge.
But with some DBAL or ORM it could be simplified. Say, by using a DBAL I wrote, it could be done in a quite neat way:
First define your variables based on user input.
$name = 'Bill';
$year = NULL;
$room = ['g23','f43','g43'];
$type = NULL;
$day = 4;
$time = NULL;
Then write a query where every variable is used twice
$sql = "SELECT * pro_files WHERE name=?s
(AND ?s is NULL OR year = ?s)
(AND ?a is NULL OR type = ?a)
(AND ?a is NULL OR room = ?a)
(AND ?s is NULL OR day = ?s)
(AND ?s is NULL OR time = ?s)";
And finally run the query:
$data = $db->getAll($sql,$name,$year,$year,$room,$room,$type,$type,$day,$day,$time,$time);
It will return the search result based on non-null values provided.
I only have to mention that prepared statements are only emulated here, but it is as safe, as native ones.
By the way, I would like to see an approach from other DBAL or ORM. To recommend one is one thing and to show a working example is another.
Upvotes: 2