Andy Andy - 29 days ago 8
PHP Question

Writing a PDO search query from a PHP array

I'm building an application using PHP 7 and a PDO connection to a MySQL database.

One part of the application contains a search form which allows a user to search for a training course by 3 different fields: the course category, the course name, and a date.

The types of elements on the form are:


  1. Course category - dropdown, with numerical (int) ID's.

  2. Course name - text input

  3. Date - date picker (using HTML 5
    type="date"
    parameter to get a calendar in the browser).



These fields can be used in conjunction, or on their own. This means a user could search, for example, just by (1), or (2 & 3), or all (1 & 2 & 3).

I've written the PHP to get the POST data and it's now in an array - for example:

$search_data = [
'category' => 3,
'name' => 'Hazard training',
'date' => ''
]


I want to use this within a PDO query but I don't know what the best way to write it is because (1) and (3) would be an
=
query condition, whereas (2) is a
LIKE
. My solution was going to be looping through the search terms and then trying to construct a query, e.g.

$sql = ' WHERE ';
foreach ($search_data as $key => $value) {
if ($key == 'category') {
$sql .= ' category = ' . $value;
}
if ($key == 'course_name') {
$sql .= ' course_name LIKE % ' . $value ' % ';
}
if ($key == 'date') {
$sql .= ' date = ' . $value;
}
}


The trouble with this is it doesn't work because of having to bind the parameters in PDO. It also doesn't work because I can't find a way to get the
AND
between each query (if there is a preceding statement).

I'm lost with this now and unsure what the best way to write this is.

Any help would be appreciated.

Edit: I realise that hardcoding the names, e.g.
($key == 'course_name')
isn't ideal, but this is only being done because of the different query conditions (
LIKE
vs
=
). I assume that one could make
$search_data
multi-dimensional to say which type of query it was, but this is beyond my initial problem and probably another post.

Answer

Here`s a simple solution to your problem:

$sql = 'SELECT ..... FROM ... WHERE 1 ';
$where = '';
$pdoData = [];

foreach ($search_data as $key => $value) {
    if(!$value) continue; // skip empty values

    if ($key === 'category') {
        $pdoData[':category'] = $value;
        $where .= ' AND category = :category ';
    }
    if ($key === 'course_name') {
        $pdoData[':course_name'] = $value;
        $where .= ' AND course_name LIKE % :course_name % ';
    }
    if ($key === 'date') {
        $pdoData[':date'] = $value;
        $where .= ' AND date = :date ';
    }
}

$sql = $sql.$where;

And you have $pdoDate array holding the binded data.