Question

I am using the fatfree framework, and on the front-end I am using jQuery datatables plugin with server-side processing. And thus, my server-side controller may or may not receive a variable number of information, for example a variable number of columns to sort on, a variable number of filtering options and so forth. So if I don't receive any request for sorting, I don't need to have a ORDER BY portion in my query. So I want to generate the query string in parts as per certain conditions and join it at the end to get the final query for execution. But if I do it this way, I won't have any data sanitization which is really bad.

Is there a way I can use the frameworks internal sanitization methods to build the query string in parts? Also is there a better/safer way to do this than how I am approaching it?

Was it helpful?

Solution

Just use parameterized queries. They are here to prevent SQL injection.

Two possible syntaxes are allowed:

  1. with question mark placeholders:

    $db->exec('SELECT * FROM mytable WHERE username=? AND category=?',
      array(1=>'John',2=>34));
    
  2. with named placeholders:

    $db->exec('SELECT * FROM mytable WHERE username=:name AND category=:cat',
      array(':name'=>'John',':cat'=>34));
    

EDIT:

The parameters are here to filter the field values, not the column names, so to answer more specifically to your question:

  • you must pass filtering values through parameters to avoid SQL injection
  • you can check if column names are valid by testing them against an array

Here's a quick example:

$columns=array('category','age','weight');//columns available for filtering/sorting
$sql='SELECT * FROM mytable';
$params=array();

//filtering
$ctr=0;
if (isset($_GET['filter']) && is_array($_GET['filter'])
  foreach($_GET['filter'] as $col=>$val)
    if (in_array($col,$columns,TRUE)) {//test for column name validity
      $sql.=($ctr?' AND ':' WHERE ')."$col=?";
      $params[$ctr+1]=$val;
      $ctr++;
    }

//sorting
$ctr=0;
if (isset($_GET['sort']) && is_array($_GET['sort'])
  foreach($_GET['sort'] as $col=>$asc)
    if (in_array($col,$columns,TRUE)) {//test for column name validity
      $sql.=($ctr?',':' ORDER BY ')."$col ".($asc?'ASC':'DESC');
      $ctr++;
    }

//execution
$db->exec($sql,$params);

NB: if column names contain weird characters or spaces, they must be quoted: $db->quote($col)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top