So I have been using prepared statements for a while and for a number of projects and it has been a really good clean way to interact with the MySQL db, but today I have come across a strange problems.
My prepared statement has started adding extra ‘ to the sql statements and for the life of me I have no idea why…
so here is the code:
<?php
$sortby="ORDER BY submit_date DESC";
$offset = 3;
$sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' :sortby LIMIT :offset, 9";
$stmt = $this->_db->prepare($sql);
$stmt->bindParam(":sortby", $sortby, PDO::PARAM_STR);
$stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
$stmt->execute();
?>
so the above doesnt return anything, so looking at the database logs, this is what the query looks like
SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' 'ORDER BY submit_date DESC' LIMIT 3, 9
it seems to have put an extra set of ‘ ‘ around the “ORDER BY submit_date DESC”, but yet hasnt around the offset?
Can anyone spot the problem as its driving me mad 🙂
Thank you in advance!
Solution, thanks to the guys that posted, you were correct, I split the fields out to parts and works like a charm. Code solution below:
<?php
$sortfield="submit_date";
$sortway="DESC"
$offset = 3;
$sql = "SELECT img_id, img_name, submit_date FROM tbl_images WHERE img_active='y' ORDER BY :sortfield :sortway LIMIT :offset, 9";
$stmt = $this->_db->prepare($sql);
$stmt->bindParam(":sortfield", $sortfield, PDO::PARAM_STR);
$stmt->bindParam(":sortway", $sortway, PDO::PARAM_STR);
$stmt->bindParam(":offset", $offset, PDO::PARAM_INT);
$stmt->execute();
?>
Have a look at the documentation for
mysqli_stmt::prepare:Basically, anything structural to the query is not allowed to be a bound parameter. Only data can be sent in this way.
PDO’s prepared statements work in effectively the same way. In your case, however, PDO is a bit stupid, because it’s running in “emulate prepares” mode (which is the default, but you should turn it off to get the most from PDO). It basically does all the substitution itself, rather than sending the query and the data to the server separately. It sees that the data is a string and thinks “aha, a string: I need to put quotes around this.” You therefore end up with your malformed query.
The solution is not to build up structural parts of your query with bound parameters. Either substitute them in yourself with concatenation, or (and this is better) have alternative query strings for different settings. This is the most secure way: anything involving concatenation is a recipe for insecurity.
Oh, and turn PDO emulate prepares off!