PDOException SQLSTATE[HY093] after upgrading to PHP 8.1 - php

today I encounter an issue after upgrading from PHP 7.4 to PHP 8.1.
All the time I was using this code to establish an MySQL connection:
<?php
$kundencode=$_SESSION['kdnr'];
$i=0;
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr='$kundencode' ORDER BY rgnr DESC");
$q->execute([$_SESSION['id']]);
$res = $q->fetchAll();
foreach ($res as $row) {
$i++;
?>
This worked fine, but when using PHP 8.1 my system throws:
Fatal error: Uncaught PDOException: SQLSTATE[HY093]: Invalid parameter number: number of bound variables does not match number of tokens in /home/clients-de/public_html/rechnungen2.php:60 Stack trace: #0 /home/clients-de/public_html/rechnungen2.php(60): PDOStatement->execute(Array) #1 {main} thrown in...
I can't see any mistake!?
What's the difference here between PHP 7.4 and 8.1?
Thank you for help...

The change that you encountered is that before PHP 8, PDO's error mode was set to silent by default. If it encountered any errors, it would just ignore them. This has now changed to the exception mode; every time an error is encountered, an exception will be thrown. So the issue was there before, it just remained unreported.
About the actual issue: you should really read up about prepared statements, they will make your code a lot safer. You're not providing any placeholders for prepared variables in your query, but you are passing them in the following line (which results in the exception):
$q->execute([$_SESSION['id']]);
As far as I see, the session ID is completely unnecessary for your query, but you could pass your customer number as a variable. The following should fix your issue:
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=? ORDER BY rgnr DESC");
$q->execute([$kundencode]);

First of all, you shouldn't inline raw variables in query, use param binding.
Invalid parameter number: number of bound variables does not match number of tokens
This means that count of array passed into PDO::execute() method is different with count of params in query.
For your case, maybe this solution helps you:
// let's assume there is '5'
$kundencode=$_SESSION['kdnr'];
$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=:kundencode ORDER BY rgnr DESC");
// pass $kundencode into query
$q->bindValue('kundencode', $kundencode);
// SELECT * FROM qi_rechnungen WHERE kdnr='5' ORDER BY rgnr DESC
$q->execute();
If you want to pass $_SESSION['id'] into query, you must specify it in query template explicitly

#vixducis : That's exactly what I finally did yesterday - and got it to work as desired:
$q = $pdo->prepare("SELECT * FROM qi_domains WHERE kdnr = ? AND aktiv = ? ORDER BY id DESC");
$q->execute([$_SESSION['kdnr'], 0]);
So let me thank you all for your kind support!

Related

Error accessing MySQL database with PHP object (nested queries)

I want to get some data from a Sphinx server and pass it to MySQL to execute some queries. I'm new to PHP so probably I'm missing something here. I've looked for similar questions but can't find anything so maybe you can help me.
The error is in the first while. I'm pretty sure it's due to the $rown variable but don't know the reason. (I've verified that I can retrieve data from the connections so it is passing the data where the error lies - could be the sql syntax of the query but that seems fine).
Edited the code thanks to the comments below, now I get the error: Warning: mysqli_fetch_object() expects parameter 1 to be mysqli_result, boolean given in C:\Apache24\htdocs\test3.php on line 20. This is because the query failed, I still suspect it is because $rown.
$sphinxcon = mysqli_connect...
$mysqlcon = mysqli_connect...
$query = "SELECT names FROM iproducts LIMIT 0,1000";
$raw_results= mysqli_query($sphinxcon, $query);
//Until here works ok, now I want to pass $raw_results to MySQL
while ($row = mysqli_fetch_object($raw_results)) {
$rown = $row->names;
$mquery = "SELECT text FROM claims WHERE EXISTS ($rown) LIMIT 0,1000";
$mysqlresults = mysqli_query($mysqlcon, $mquery);
while ($final = mysqli_fetch_object($mysqlresults)) //this is line 20
{
printf ("%s<br />", $final->text);
}
}
Thanks :)
Well $row contains an object, so would have to use it as such, maybe
$rown = (string)$row->names;
... assuming you want the variable to contain the 'names' attribute you just SELECTed from Sphinx index.
As for the mysql EXISTS(), no idea what you really doing here, seems confused. How you structured it currently suggests that 'names' attribute in sphinx contains a complete SELECT query, that mysql could execute for the exists condition. That seems unlikely.
Guessing you meaning to more normal query something like
$mquery = "SELECT text FROM claims WHERE text LIKE '%$rown%' LIMIT 0,1000";
But that is subject to SQL injection, particully if names might contain single quotes. SO should escape it. Perhaps
$rown = mysqli_real_escape_string($mysqlcon, $row->names);
But might be worth reading up on prepared queries.
btw, the 'Error' you getting, is because you creating an invalid query and not dealing with it. So $mysqlresults is FALSE.
$mysqlresults = mysqli_query($mysqlcon, $mquery) or die("Mysql Error: ".mysqli_error($link)."\n");

MySQL Update and Select in one statement

I am attempting to do an UPDATE and a SELECT in the same sql statement. For some reason, the below code is failing.
$sql = "UPDATE mytable SET last_activity=CURRENT_TIMESTAMP,
info1=:info1, info2=:info2 WHERE id = {$id};";
$sql .= "SELECT id, info1, info2 FROM myTable
WHERE info1 >=:valueA AND info2>:valueB;"
$stmt = $conn->prepare($sql);
$stmt->bindParam(":info1", $info1);
$stmt->bindParam(":info2", $info2);
$stmt->bindParam(":valueA", $valueA);
$stmt->bindParam(":valueB", $valueB);
$stmt->execute();
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode($result);
QUESTION: what might I be doing wrong? I have been spending hours on this issue knowing that it's probably a small error right under my nose.
Edited:
I obtained this error message when loading the page that contains the php code:
Uncaught exception 'PDOException' with message 'SQLSTATE[HY000]:
General error' in ajaxCall.php:89 Stack trace: #0 ajaxCall.php(89):
PDOStatement->fetchAll(2) #1 {main} thrown in ajaxCall.php on line 89
I am using ajax to call the php page that contains the above code, and when I load the php page from the browser, I get the above error message.
Line 89 is: $result = $stmt->fetchAll(PDO::FETCH_ASSOC);
Since you are running two queries, you need to call nextRowset to access the results from the second one.
So, do it like this:
// code
$stmt->execute();
$stmt->nextRowset();
// code
When you run two or more queries, you get a multi-rowset result. That means that you get something like this (representation only, not really this):
Array(
[0] => rowset1,
[1] => rowset2,
...
)
Since you want the second set -the result from the SELECT-, you can consume the first one by calling nextRowset. That way, you'll be able to fetch the results from the 'important' set.
(Even though 'consume' might not be the right word for this, it fits for understanding purposes)
Executing two queries with one call is only allowed when you are using mysqlnd. Even then, you must have PDO::ATTR_EMULATE_PREPARES set to 1 when using prepared statements. You can set this using:
$conn->setAttribute(PDO::ATTR_EMULATE_PREPARES, 1);
Alternatively, you can use $conn->exec($sql), which works regardless. However, it will not allow you to bind any data to the executed SQL.
All in all, don't execute multiple queries with one call.

PDO mysql error

I am currently working on a project for a client but because I am new to pdo I have no clue how to hand the error it keeps spitting out. The code I am working with is not mine either, so that adds a bit of confusion to the mix. It keeps telling me:
Query failed: 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 '' at line 1
I have narrowed down the error to these lines:
$regid = $dbh->lastInsertId('');
$dupsid = true;
while ($dupsid){
srand((double)microtime()*1000000);
$maxrand = 100000000;
$rand_sid = rand();
$check_sid = "select reguniqid from v_events_registrants where reguniqid = :RAND_SID";
$stmt = $dbh->prepare($check_sid);
$stmt->bindValue(':RAND_SID', $rand_sid);
$stmt->execute();
$num_result = $stmt->rowCount();
if ($num_result == 0) $dupsid = false;
}
$uniqid_upd = "update v_events_registrants set reguniqid = :RAND_SID where registrant_id = :REGID";
$stmt = $dbh->prepare($uniqid_upd);
$stmt->bindValue(':RAND_SID', $rand_sid);
$stmt->bindValue(':REGID', $regid);
$stmt->execute();
in this case here $reg is the primary key of the table in which the last few items were added. Initially I thought that was the issue but when I cleared it of ', and " I get an invalid id error, which I am guessing is from the next execution of the pdo. Please help as this error is really starting to hold me back from completing this project for my client.
Your first line defines $reg, then you try to use the undefined $regid
Nearly positive $regid is not defined, at least not within the scope of the code you included.
Trace that variable back or define at as something and you should be fixed.
Most likely your error lies somewhere else.
So, first of all get rid ov any try..catch blocks in your code
Then turn error reporting on
Then run your code again and find the real place where error occurs from the stack trace.
Then you get to erroneous query, write it this way
select
reguniqid
from
v_events_registrants
where
reguniqid
=
:RAND_SID
and watch the line number - it will help you locate the problem spot.
As your $rand_sid is of type integer, both times you use bindValue for $rand_sid you should add the datatype PDO::PARAM_INT (it takes PDO::PARAM_STR as default), like this:
$stmt->bindValue(':RAND_SID', $rand_sid, PDO::PARAM_INT);

SQL: number of bound variables

i read few topics here but i dont find right answer.
I am getting this error:
Warning: PDOStatement::execute() [pdostatement.execute]: SQLSTATE[HY093]: Invalid
parameter number: number of bound variables does not match number of tokens in
....
PHP code:
$sarray[':item1'.$i] = $ws->getCell($item1.$i)->getValue();
$sarray[':item2'.$i] = $ws->getCell($item2.$i)->getValue();
$sarray[':item3'.$i] = $ws->getCell($item3.$i)->getValue();
$sql = update ...
$sql1 = $DB->prepare($sql);
$sql1->execute($sarray);
And after executing i am getting Error(it is at top).
Problem:
Problem is that, $sarray[':item1'.$i] and $sarray[':item2'.$i] have same definition and if add third $sarray[':item3'.$i] it makes fault, but i dont know how to fix it.
Thanks for any response.

Why isn't PHP PDO protecting my query from injection?

I'm still in the progress of learning PDO fully, but I was kind of surprised when I checked this evening if it worked to SQL Inject the URL parameter, and to my surprise, it did work. So I started thinking; the posted values are supposed to be sanitized automatically using PDO - prepared statements, which means there must be something wrong with my SQL query, am I right?
I'm having a page that needs a GET variable in order to gather corresponding data from my database with that ID. I have created a function that includes preparing the query, and as well as executing it to simplify the coding process. The code I have written now looks like:
$request = $_GET['movie'];
$sql = "SELECT * FROM `movies` WHERE `url` = '$request'";
$db = new database;
$db->setDBC();
$process = $db->executeQuery($sql);
$cmd = $process->fetch(PDO::FETCH_NUM);
$title = $cmd[1];
And the PDO Exception I get is:
Fatal error: 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 ''21-31282 ''' at line 1' in C:\xampp\htdocs\filmvote\include\databaseClass.php:33 Stack trace: #0 C:\xampp\htdocs\filmvote\include\databaseClass.php(33): PDOStatement->execute() #1 C:\xampp\htdocs\filmvote\recension.php(9): databaseManagement->executeQuery('SELECT * FROM `...') #2 {main} thrown in C:\xampp\htdocs\filmvote\include\databaseClass.php on line 33
You get this kind of error when adding ' or 1-1 to the URL. What can I do about this? Really grateful for help.
the posted values are supposed to be sanitized automatically using PDO
Nope. Only if you use actual prepared statements like so:
$stmt = $dbh->prepare("SELECT * FROM `movies` WHERE `url` = ?");
if ($stmt->execute(array($_GET['movie']))) // <-- This sanitizes the value
{
// do stuff
}
will your the values you insert be automatically sanitized, and your query protected from SQL injection.
Otherwise, your SQL query will be executed like any old mysql_query(), and is vulnerable. PDO can not take a query and then automatically sanitize the vulnerable parts. That's not possible.
Try prepared statements:
$query = $db->prepare("SELECT * FROM `movies` WHERE url = ?");
$query->execute(array($request));
$result = $query->fetch(PDO::FETCH_ASSOC);

Categories