Search code examples
phpmysqlloopspdoparameterized

PDO Parameterized SELECT statement with looped conditional


I am switching a web-app I am working on to PDO (from the horrible and unsafe mysql_query) and am having some difficulty with how to adapt an existing query to the new format. The query finds media items of a certain file types:

The GET is formatted like: jpg,png,gif

(The code below was escaping things but has been simplified for this example)

$query   = "SELECT * FROM `media` WHERE `active` = '1' AND `thumb` IS NULL ";
if($_GET['extensions']){
    $extensions = array_filter(explode(',',str_replace(' ','',strtolower($_GET['extensions']))));
    foreach($extensions as $extension){
        $extension_sql[] = "`type` = '$extension' ";
    }
    if(count($extension_sql) > 0){
        $query .= 'AND (' . implode('OR ', $extension_sql) . ')';
    }
}
$query .= "ORDER BY `created` DESC ";
$result = mysql_query($query);
while($media = mysql_fetch_array($result)){     
    // Do stuff
}

Perhaps I was going about this in a totally backwards way and it should be using an IN() function but regardless, I need to convert this into a parameterized PDO statement such as:

$sth = $dbh->prepare("SELECT * FROM `media` WHERE `active` = '1' AND `thumb` IS NULL AND `type` IN(:set) ORDER BY `created` DESC ");
$types = implode(',', array_filter(explode(',',str_replace(' ','',strtolower($_GET['extensions']))));
$sth->bindParam(':set', $types);
$sth->execute();
while($datatype_option_row = $sth->fetch()){
    // Do stuff
}

Clearly this won't work... but I am trying to be efficient and secure with little success. I might be able to loop over files-types to create the SQL and then loop again over the binds... but wanted to see if anyone here had sage advice for a different approach.

TL;DR: Trying to find the best way to parameterize a dynamic lists of SQL conditionals.

Thanks in advance!


Solution

  • Figured it out, the key was the FIND_IN_SET function since it's a short list of types:

    $type_sql = ($_GET['extensions'])? "AND FIND_IN_SET(`type`, :type)" : "";
    $sth = $dbh->prepare("SELECT * FROM `media` WHERE `active` = '1' AND `thumb` IS NULL $type_sql ORDER BY `created` DESC ");
    $sth->bindParam(':type', $_GET['extensions']);
    $sth->execute();
    while($media = $sth->fetch()){
        // Do stuff
    }