Setting PDO/MySQL LIMIT with Named Placeholders [duplicate] - php

This question already has answers here:
How can I pass an array of PDO parameters yet still specify their types?
(3 answers)
Closed 7 years ago.
I'm having an issue binding the LIMIT part of an SQL query. This is because the query is being passed as a string. I've seen another Q here that deals with binding parameters, nothing that deals with Named Placeholders in an array.
Here's my code:
public function getLatestWork($numberOfSlides, $type = 0) {
$params = array();
$params["numberOfSlides"] = (int) trim($numberOfSlides);
$params["type"] = $type;
$STH = $this->_db->prepare("SELECT slideID
FROM slides
WHERE visible = 'true'
AND type = :type
ORDER BY order
LIMIT :numberOfSlides;");
$STH->execute($params);
$result = $STH->fetchAll(PDO::FETCH_COLUMN);
return $result;
}
The error I'm getting is: Syntax error or access violation near ''20'' (20 is the value of $numberOfSlides).
How can I fix this?

The problem is that execute() quotes the numbers and treats as strings:
From the manual - An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
<?php
public function getLatestWork($numberOfSlides=10, $type=0) {
$numberOfSlides = intval(trim($numberOfSlides));
$STH = $this->_db->prepare("SELECT slideID
FROM slides
WHERE visible = 'true'
AND type = :type
ORDER BY order
LIMIT :numberOfSlides;");
$STH->bindParam(':numberOfSlides', $numberOfSlides, PDO::PARAM_INT);
$STH->bindParam(':type', $type, PDO::PARAM_INT);
$STH->execute();
$result = $STH->fetchAll(PDO::FETCH_COLUMN);
return $result;
}
?>

I'd suggest binding the params and forcing their type:
$STH->bindParam(':numberOfSlides', $numberOfSlides, PDO::PARAM_INT);
$STH->execute();

Related

Need a 2023 answer to PDO BIND IN clause [duplicate]

This question already has answers here:
PHP - Using PDO with IN clause array
(9 answers)
Closed 24 days ago.
I did have this code working but it was not secure from SQL injection so I tried to update it. The user submit filter requirements which come from check boxes, I take them from post, and replace them with ?, I then implode, and bind them back together for the IN clause.
I feel like I am a couple of lines of code away from getting this. What am I doing wrong? I have echoed out after implode and it shows the right amount of ? corresponding to the selections. Is the problem in my execute statement?
if(isset($_POST['songgenre'])){
$songgenre = $_POST['songgenre'];
$placeholderssonggenre = array_fill(1, count($songgenre), '?');
$songgenrefilter = implode(',', $placeholderssonggenre);
}else{
$songgenre ='';
$genreempty = '';
}
$sql = "SELECT * FROM music_db WHERE songgenre IN ($songgenrefilter)";
$stmt = $conn->prepare($sql);
$res = $stmt->execute($songgenre);
if ($res !== FALSE) {
$results = $res->rowCount();
echo($results);
} else {
echo "Code Failed";
}
I know really how frustrating it could be. Well, it seems that following things are missing there. Try it:
When you're using the IN clause, you need to pass an array of values to the execute() method, not a single variable. This means that you should be passing $songgenre directly to the execute() method, instead of using it to create the $placeholderssonggenre variable.
You should bind the parameters to the statement before executing it, not after. You can use the bindValue() method to bind the values to the placeholders in the query.
When you execute the statement, you should use the fetchAll() method to retrieve the rows, instead of rowCount().
Here's the correct code:
if(isset($_POST['songgenre'])){
$songgenre = $_POST['songgenre'];
$placeholders = array_fill(0, count($songgenre), '?');
$placeholders = implode(',', $placeholders);
} else {
$songgenre ='';
$placeholders = '';
}
$sql = "SELECT * FROM music_db WHERE songgenre IN ($placeholders)";
$stmt = $conn->prepare($sql);
foreach ($songgenre as $i => $value) {
$stmt->bindValue($i + 1, $value);
}
$stmt->execute();
$results = $stmt->fetchAll();
Another option more elegant
if(isset($_POST['songgenre'])){
$postfilter = [
'songgenre' => ['filter' => FILTER_SANITIZE_STRING] // always sanitize
];
$filter_post_array = filter_var_array($_POST, $postfilter);
$filtered = $filter_post_array['songgenre'];
} else {
$filtered = [];
}
$sql = "SELECT * FROM music_db WHERE songgenre IN (:songgenrefilter)";
$stmt = $conn->prepare($sql);
$stmt->bindValue(':songgenrefilter',implode(',',$filtered);
$stmt->execute();
$result = $stmt->fetchAll();

Is there a solution to "object of class mysqli_result could not be converted to string"? [duplicate]

This question already has answers here:
Object of class mysqli_result could not be converted to string
(5 answers)
Closed 1 year ago.
I searched the Internet for some Solutions but none of it works and I can't find out why. I'm new to PHP and MYSQL/MyAdmin so I really don't understand what I did wrong.
I've already tried several commands and "while $row = $result->fetch_array()" and stuff like that.
$Word = "SELECT Word FROM RandWord WHERE Number = '$Number'";
$Word = mysqli_query($data, $Word);
echo $Word;
$Amount = count($Word);
I want it to Output the "Count($Word);" for me, but it can't even echo because it can not be converted into a string. I want to see the word and use it.
You need to actually fetch the results first, before you can use it. You are also vulnerable to SQL injection attacks, so use a prepared statement instead.
In your code $Word is a result-object, which holds information - but you need to use a fetching method to retrieve the data first. count() in PHP is only usable on arrays (or on objects, but not that object which you get from mysqli_query()).
$query = "SELECT Word FROM RandWord WHERE Number = ?";
$stmt = $data->prepare($query);
$stmt->bind_param("s", $Number);
$stmt->execute();
$stmt->bind_result($word);
while ($stmt->fetch()) {
echo $word;
}
$stmt->close();
If you want it to be a count of each word, you have to run a query using the MySQL function COUNT() instead.
$query = "SELECT Word, COUNT(Word) as cnt FROM RandWord WHERE Number = ? GROUP BY Word";
$stmt = $data->prepare($query);
$stmt->bind_param("s", $Number);
$stmt->execute();
$stmt->bind_result($word, $count);
while ($stmt->fetch()) {
echo $word." has count ".$count;
}
$stmt->close();

mysql limit clause not working alongside php bindvalue [duplicate]

This question already has answers here:
PHP PDO bindParam was falling in a foreach
(2 answers)
Closed 4 years ago.
After attempting to create a pagination, I noticed that PHP's bindValue does not work when using alongside MySQL's ORDER BY or LIMIT clauses.
This is pretty strange considering it'll work anywhere else within MySQL (at least as far as I'm aware). For example, this works completely fine:
SELECT * FROM table WHERE foo = ? AND bar = ?
However, when attempting something like:
SELECT * FROM table ORDER BY date DESC LIMIT ?, ?
It will return an empty object.
This is how I'm executing my queries (please note that this is all simplified, and the functions that I'm using are all apart of a class):
// query function
function query($sql, $params){
if($query = $pdo->prepare($sql)){
$x = 1;
if(count($params)){
foreach($params as $param){
$query->bindValue($x, $param);
$x++;
}
}
if($query->execute()){
return $query->fetchAll(PDO::FETCH_OBJ);
} else {
return false;
}
}
}
// executing a query (this will return an empty object)
$query = query("SELECT * FROM table ORDER BY date DESC LIMIT ?, ?", array(0, 10));
var_dump($query);
Can't seem to figure this one out, so all help is appreciated,
Cheers.
You Params will be included as Strings. Use a constant to tell bindValue to bind the value as an int.
$query->bindParam(2, $x, PDO::PARAM_INT);

Error while using PDO prepared statements and LIMIT in query [duplicate]

This question already has answers here:
How to apply bindValue method in LIMIT clause?
(11 answers)
Closed 7 years ago.
I'm using PDO in my application. But I have a problem while I'm working with prepared statements in a query that contains LIMIT. What's the problem?
Codes:
$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));
Error:
check the manual that corresponds to your MySQL server version for the right syntax to use near ''0', '20''
You can do like this:
$sql = SELECT * FROM tbl_news ORDER BY date DESC LIMIT :start, :rows";
$q = $db->prepare($sql);
$q->bindParam(':start', $start, PDO::PARAM_INT);
$q->bindParam(':rows',$rows, PDO::PARAM_INT);
Regarding to post LIMIT keyword on MySQL with prepared statement , the code below could solve my problem.
$db->setAttribute(PDO::ATTR_EMULATE_PREPARES, FALSE);
Thanks Álvaro G. Vicario and Maerlyn
It is a known bug which was fixed in 5.5.6 from memory.
From the article:
LIMIT doesn't allow variables in any context.
Its arguments must be integer constants.
Further Edit: (There is contention on the matter)
User variables are accepted arguments of LIMIT clause in prepared statements, and SQL syntax for prepared statements can be used in stored procedures.
Third Edit:
This link explains that these should work with prepared statements.
I just stumbled upon the same problem. For me, using my own statement class (extending PDOStatement) with my own execute() method fixed it.
This is the class:
class MyPDOStatement extends PDOStatement {
public function execute($input_parameters = null) {
if (is_array($input_parameters)) {
$i = 1;
foreach ($input_parameters as $p) {
// default to string datatype
$parameterType = PDO::PARAM_STR;
// now let's see if there is something more appropriate
if (is_bool($p)) {
$parameterType = PDO::PARAM_BOOL;
} elseif (is_null($p)) {
$parameterType = PDO::PARAM_NULL;
} elseif (is_int($p)) {
$parameterType = PDO::PARAM_INT;
}
// parameters passed to execute() are input-only parameters, so use
// bindValue()
$this->bindValue($i, $p, $parameterType);
$i++;
}
}
return parent::execute();
}
}
To tell PDO to use this statement class instead of the default one, do this:
$db = new PDO(...);
$db->setAttribute(PDO::ATTR_STATEMENT_CLASS, array('MyPDOStatement'));
Now the code in the question will work:
$start = 0;
$rows = 20;
$sql = "SELECT * FROM tbl_news ORDER BY date DESC LIMIT ?, ?";
$q = $db->prepare($sql);
$q->execute(array($start , $rows));
The only thing you have to make shure is that the variables bound to the statement have the correct type, integer. If you have a numeric string, e.g. from the $_GET array, you can do something like this:
if (isset($_GET['start']) && is_numeric($_GET['start'])
&& is_int($_GET['start'] + 0) {
$start = (int) $_GET['start'];
}
I'm not shure if there is an easier way for the last thing, but at least it works fine for me.
date is a reserved word you have to wrap it with back-ticks

PDO and SQL IN statements [duplicate]

This question already has answers here:
Can I bind an array to an IN() condition in a PDO query?
(23 answers)
Closed 9 years ago.
Im using a sequel for search like this using PDOs
$states = "'SC','SD'";
$sql = "select * from mytable where states in (:states)";
$params = array(':states'=>$states);
and I use my function
$result = $this->selectArrayAssoc($sql, $params);
where my selectArrayAssoc function as following
public function selectArrayAssoc($sql, $params = array())
{
try {
$sth = $this->db->prepare($sql);
$sth->execute($params);
$result = $sth->setFetchMode(PDO::FETCH_ASSOC);
return $sth->fetchAll();
} catch(PDOException $e) {
print $e->getMessage();
//Log this to a file later when in production
exit;
}
}
it does not take the quoted variables, I think it is suppressing, in such cases how to deal with this.
When using prepared statement placeholders (parameter binding) in general, each occurrence of a placeholder holds exactly one variable.
You're trying to pass several. What's happening is basically that your parameters are escaped: Your :states is replaced with '''SC'',''SD''' or '\'SC\',\'SD\'' internally, rather than with just the raw 'SC','SD' that you want.
pinkgothic is absolute correct. But I think you got the problem, that you have an array of 'states' and want work with this array. You've to prepare the Placeholder for each value in the query.
$states = array('SC','SD');
$phArray = array();
$valArray = array();
foreach($ids AS $key=>$value){
array_push($phArray, ':PH' . $key);
$valArray[':PH' . $key] = $value;
}
$sql = 'select * from mytable where states in (' . implode(',', $phArray) . ')';
$params = array($valArray);
$result = $this->selectArrayAssoc($sql, $params);

Categories