PDOException SQLSTATE[HY093] 升级到 PHP 8.1 后

PDOException SQLSTATE[HY093] after upgrading to PHP 8.1

提问人:Kayleigh 提问时间:8/27/2022 更新时间:8/28/2022 访问量:637

问:

今天我从PHP 7.4升级到PHP 8.1后遇到了一个问题。 我一直在使用此代码来建立MySQL连接:

<?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++;
                ?>

这工作正常,但是当使用 PHP 8.1 时,我的系统抛出:

致命错误:未捕获的 PDOException:SQLSTATE[HY093]:参数编号无效:绑定变量数与 /home/clients-de/public_html/rechnungen2.php:60 中的令牌数不匹配 堆栈跟踪:#0 /home/clients-de/public_html/rechnungen2.php(60):PDOStatement->execute(Array) #1 {main} 抛入...

我看不出有什么错误!? PHP 7.4 和 8.1 有什么区别?

谢谢你的帮助...

php sql 异常 pdo

评论

0赞 8/27/2022
kdnr='$kundencode'修复它导致的错误
4赞 GrumpyCrouton 8/27/2022
您使用的准备错误,不应将值连接到查询中。您应该使用占位符并按原样传入值。基本上,将连接的值替换为execute()?
0赞 Kayleigh 8/27/2022
@Dean:谢谢,但我认为这不可能是原因。因为当将 WHERE kdnr='$kundencode' 替换为 WHERE kdnr='4444'(实值)时,没有任何变化。
0赞 Kayleigh 8/27/2022
@GrumpyCrouton :与 concantenated 值相同,替换为 “?”。没有更改,但附加错误:“警告:未定义的数组键”?

答:

1赞 Tony Sol 8/27/2022 #1

首先,您不应该在查询中内联原始变量,而是使用参数绑定

参数编号无效:绑定变量数与令牌数不匹配

这意味着传递到方法中的数组计数与查询中的参数计数不同。PDO::execute()

对于您的情况,也许此解决方案可以帮助您:

// 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();

如果要传入查询,则必须在查询模板中显式指定它$_SESSION['id']

4赞 vixducis 8/27/2022 #2

您遇到的更改是,在 PHP 8 之前,PDO 的错误模式默认设置为静音。如果它遇到任何错误,它就会忽略它们。现在已更改为异常模式;每次遇到错误时,都会抛出异常。所以这个问题以前就存在,只是没有报告。

关于实际问题:你真的应该阅读准备好的语句,它们会让你的代码更安全。您没有为查询中的预处理变量提供任何占位符,而是在以下行中传递它们(这会导致异常):

$q->execute([$_SESSION['id']]);

据我所知,会话 ID 对于您的查询完全没有必要,但您可以将您的客户编号作为变量传递。以下方法应该可以解决您的问题:

$q = $pdo->prepare("SELECT * FROM qi_rechnungen WHERE kdnr=? ORDER BY rgnr DESC");
$q->execute([$kundencode]);
-1赞 Kayleigh 8/28/2022 #3

@vixducis : 这正是我昨天终于做的 - 并让它按预期工作:

$q = $pdo->prepare("SELECT * FROM qi_domains WHERE kdnr = ? AND aktiv = ? ORDER BY id DESC");
$q->execute([$_SESSION['kdnr'], 0]);

因此,让我感谢大家的支持!

评论

0赞 Community 9/1/2022
正如目前所写的那样,你的答案尚不清楚。请编辑以添加其他详细信息,以帮助其他人了解这如何解决所提出的问题。您可以在帮助中心找到有关如何写出好答案的更多信息。