views:

111

answers:

3

I'm trying to sort data by different fields ascending and descending. But I have different mysql pdo statements for the 4 fields I have (8 queries total):

$stmt1 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field1 DESC");
$stmt2 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field1 ASC");
$stmt3 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field2 DESC");
$stmt4 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field3 ASC");
$stmt5 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field3 DESC");
$stmt6 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field3 ASC");
$stmt7 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field4 DESC");
$stmt8 = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY field4 ASC");

Based on input, I pick the right statement and bind and execute it.

if ($sortcode == 1){ 
   $stmt1->bindParam(':categ', $categ, PDO::PARAM_STR);
   $stmt1->execute();
   $fetched = $stmt1->fetchAll(PDO::FETCH_ASSOC);
} else if ($sortcode == 2){
   $stmt2->bindParam(':categ', $categ, PDO::PARAM_STR);
   $stmt2->execute();
   $fetched = $stmt2->fetchAll(PDO::FETCH_ASSOC);
} else if ($sortcode == 3){
   $stmt3->bindParam(':categ', $categ, PDO::PARAM_STR);
   $stmt3->execute();
   $fetched = $stmt3->fetchAll(PDO::FETCH_ASSOC);
}
//repeat the block 5 more times, for a total of 8

This doesn't look right at all. Since the select statements only differ int he name of the field and the desc/asc, is there a better way to get the $sortcode and compact the code that follows?

I guess I could state the question more specifically as: is there a way I could have a single statement/single pdo statement that binds the field name and asc/decs dynamically?

+1  A: 

You can order by column number, which can be parameterized. Using an ORDER BY in this fashion is usually clearer if you specify the columns in the select clause. I'm not sure if ASC/DESC can be parameterized, though...

Monkey Boson
could I use column name also or only column number?
Chris
A: 

You can always build the queries dynamically. Store the map between $sortcode and the columns, the SELECT * FROM tabname WHERE categ=:categ part of the query, get the right column name based on $sortcode and add the ORDER BY ... part.

Lukáš Lalinský
Is building part of the query via string concatenation like you're suggesting going to dilute the security features of pdo? `categ` is user supplied data, the rest is not since it's mine. My guess is no, but just want to double check.
Chris
All you are adding to the query is your code, not user input.
Lukáš Lalinský
+4  A: 

Use associative arrays to hold the prepared statements.

Your input is a column and a sorting method, right? So prepare the queries by:

$columns = array("field1", "field2", "field3", "field4");
$orders = array("asc", "desc");
$queries = array();
foreach($columns as $col) {
  $queries[$column] = array();
  foreach ($orders as $order) {
     $queries[$column][$order] = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY $column $order");
  }
}

Now, to look up the correct query, you don't need some synthetic code -- you just look it up by column and order directly.

To look up a query, instead of having your users input a number from 1-8, have them input a column and an order. Imagine that the column is in the variable $col and the order is in $ord. Just say $queries[$col][$ord].

If for some reason you have to use the number (why?), then you need a slightly different strategy. In that case, you store the queries by that number.

$columns = array("field1", "field2", "field3", "field4");
$orders = array("asc", "desc");
$queries = array();
$i = 0;
foreach($columns as $col) {
  foreach ($orders as $order) {
     $i = $i + 1;
     $queries[$i] = $po->prepare("SELECT * FROM tabname WHERE categ=:categ ORDER BY $column $order");
  }
}

In other words, you ought to be storing queries according to how you plan to look them up.

novalis
+1 it's easy to add sort columns, and no column numbers - yikes
Fedearne
This is a good idea, **but** it doesn't solve the big problem of still having 8 different pdo statements. So for each option, when it comes to binding time, I still have to call that distinctively-named query and bind and execute. So the main code (the 8 blocks I have above) are still the same, not reduced. +1 though for the effort, although it's not exactly what I'm asking.
Chris
I have edited the reply to provide some further explanation of how it in fact does solve your problem.
novalis