How to apply bindValue method in LIMIT clause?
Here is a snapshot of my code:
$fetchPictures = $PDO->prepare("SELECT *
FROM pictures
WHERE album = :albumId
ORDER BY id ASC
LIMIT :skip, :max");
$fetchPictures->bindValue(':albumId', $_GET['albumid'], PDO::PARAM_INT);
if(isset($_GET['skip'])) {
$fetchPictures->bindValue(':skip', trim($_GET['skip']), PDO::PARAM_INT);
} else {
$fetchPictures->bindValue(':skip', 0, PDO::PARAM_INT);
}
$fetchPictures->bindValue(':max', $max, PDO::PARAM_INT);
$fetchPictures->execute() or die(print_r($fetchPictures->errorInfo()));
$pictures = $fetchPictures->fetchAll(PDO::FETCH_ASSOC);
I get
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 ''15', 15' at line 1
It seems that PDO is adding single quotes to my variables in the LIMIT part of the SQL code. I looked it up I found this bug which I think is related: http://bugs.php.net/bug.php?id=44639
Is that what I'm looking at? This bug has been opened since April 2008! What are we supposed to do in the meantime?
I need to build some pagination, and need to make sure the data is clean, sql injection-safe, before sending the sql statement.
Solution 1:
I remember having this problem before. Cast the value to an integer before passing it to the bind function. I think this solves it.
$fetchPictures->bindValue(':skip', (int) trim($_GET['skip']), PDO::PARAM_INT);
Solution 2:
The simplest solution would be to switch the emulation mode off. You can do it by simply adding the following line
$PDO->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
Also, this mode can be set as a constructor parameter when creating a PDO connection. It could be a better solution as some report their driver doesn't support the setAttribute()
function.
It will not only solve your problem with binding, but also let you send values directly into execute()
, which will make your code dramatically shorter. Assuming the emulation mode has been already set, the whole affair will take as much as half a dozen lines of code
$skip = isset($_GET['skip']) ? (int)trim($_GET['skip']) : 0;
$sql = "SELECT * FROM pictures WHERE album = ? ORDER BY id LIMIT ?, ?";
$stmt = $PDO->prepare($sql);
$stmt->execute([$_GET['albumid'], $skip, $max]);
$pictures = $stmt->fetchAll(PDO::FETCH_ASSOC);