views:

254

answers:

2
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results";
$stmt = $dbh->prepare($sql);
$stmt->execute(array(
     'sort'  => $_GET['sort'], 
     'dir'  => $_GET['dir'], 
     'start'  => $_GET['start'],
     'results' => $_GET['results'],
     )
    );

I tried to use prepare to do the job,but $stmt->fetchAll(PDO::FETCH_ASSOC); returns nothing.

Can someone point out what's the wrong thing I am doing?

A: 

You can't bind a parameter to specify a language keyword or a field name - it has to be replacing a literal. Therefore, your limit values I think are fine, but your order by is not. It will be best for you to manually replace sort and dir in the string. Escape them but don't use the DB tools to do so, since they aren't string literals. Basically ensure no special characters are present.

firebird84
I replaced `:sort :dir` with `:sss :xxx` but still not working.
That's not what I meant. It depends on your DBMS, it appears. With MySQL, for example, you cannot use bind parameters for keywords or names. A user at php.net discovered such as well: http://www.php.net/manual/en/pdo.prepare.php#71127. If you're using a different DBMS, however, then disregard my answer.
firebird84
+1  A: 

After using :

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

I got the message :

Uncaught exception 'PDOException' with message 'SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '10'' at line 1

So, when you use an array for execute, it consider your inputs as string which is not a good idea for LIMIT

$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$sql = "SELECT * FROM table ORDER BY :sort :dir LIMIT :start, :results";
$stmt = $dbh->prepare($sql);
$stmt->bindParam(':start', $_GET['start'], PDO::PARAM_INT);
$stmt->bindParam(':results', $_GET['results'], PDO::PARAM_INT);
$stmt->bindParam(':sort', $_GET['sort']);
$stmt->bindParam(':dir', $_GET['dir']);
$stmt->execute();

$data = $stmt->fetchAll(PDO::FETCH_ASSOC);
print_r($data);
Arkh
I never see such declaration that parameters can't be used in `limit` and `order` clauses,can you provide some links for reference?Is there a complete list in which parameters can be used?
Seems like I'm wrong, only table / column names can't be parameterized. Your problem comes from your array keys in which you forgot the : (':sort' => $_GET['sort']).
Arkh
Nope,`:` is optional(it still returns nothing after adding `:`).You can see this here if you pull down enough: http://www.php.net/manual/en/pdostatement.execute.php
Problem found, answer edited.
Arkh
But pdo said: *do not include the user-input directly in the query*,how should I do it then? http://www.php.net/manual/en/pdo.prepare.php
Read the edited version, it's not using the user input directly, but binding it using bindValue.
Arkh
I think they are the same thing.
Then let's use bindParam instead of bindValue.
Arkh
It's still not working,reporting *check the manual that corresponds to your MySQL server version for the right syntax to use near 'table ORDER BY 'id' 'DESC' LIMIT 0, 20'*
I can't reproduce this when I use things like `$_GET['dir'] = 'ASC';`. What do you use to populate your $_GET array ?
Arkh
You can simply reproduce it using MySQL,what DBMS are you using?
Mysql 5.1 and php 5.3. How do you populate your $_GET array ?
Arkh