PDO 多个命名占位符不检索数据

2023-04-08php开发问题
5

本文介绍了PDO 多个命名占位符不检索数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

到目前为止,如果准备好的语句只有一个命名占位符,我编写的代码可以正常工作,但如果查询有多个条件,则不会从数据库返回任何结果.

The code I've written so far works fine if there is only one named place holder for a prepared statement but if there are multiple conditions for a query, it doesn't return any results from the database.

例如:

$query = array();
$query['columns'] = array('*');
$query['tables'] = array('esl_comments');
$query['where'] = array(
    'esl_comments.commentVisible' => array('=', 'Y')
);

工作正常.但如果我尝试:

Works fine. But if I try:

$query = array();
$query['columns'] = array('*');
$query['tables'] = array('esl_comments');
$query['where'] = array(
    'esl_comments.commentVisible' => array('=', 'Y'),
    'esl_comments.commentID' => array('=', '1'),
);

(注意附加的commentID参数)尽管mySQL数据库中有满足条件的数据,但它没有返回任何内容.

(Note the additional commentID parameter) it fails to return anything despite there being data in the mySQL database that satisfies the conditions.

我编写的 PDO 代码是:

The PDO code i've written is:

$sql ='SELECT ';
                foreach($query['columns'] as $column){ //What columnns do we want to fetch?
                    $sql.=$column . ", ";
                }
                $sql = rtrim($sql, " ,");
                $sql .=' FROM '; //Which tables will we be accessing?
                foreach($query['tables'] as $tables){
                    $sql.=$tables . ", ";
                }
                $sql = rtrim($sql, " ,"); //Get rid of the last comma
                $sql .=' WHERE ';

                if(array_key_exists('where', $query)) //check if a where clause was provided
                {
                    $fieldnames = array_keys($query['where']);
                    $count = 0;
                    $size = sizeof($fieldnames);
                    $bindings = array();
                    foreach($query['where'] as $where){

                        $cleanPlaceholder = str_replace("_", "", $fieldnames[$count]);
                        $cleanPlaceholder = str_replace(".", "", $cleanPlaceholder);
                        $sql.=$fieldnames[$count].$where[0].":".$cleanPlaceholder." AND ";
                        $bindings[$cleanPlaceholder]=$where[1];
                        $count++;
                    }
                    $sql = substr($sql, 0, -5);  //Remove the last AND
                }
                else{ //no where clause so set it to an always true check
                    $sql.='1=1';
                    $bindings=array('1'=>'1'); //Provide default bindings for the statement
                }

                $sql .= ';'; //Add the semi-colon to note the end of the query
                echo $sql . "<br/><br/>";
            //  exit();
                $stmt = $this->_connection->prepare($sql);

                foreach($bindings as $placeholder=>$bound){
                    echo $placeholder . " - " . $bound."<br/>";
                    $stmt->bindParam($placeholder, $bound);
                }

                $result = $stmt->execute();
                echo $stmt->rowCount() . " records<br/>";

                $results = $stmt->fetchAll(PDO::FETCH_ASSOC);

我正在动态构建查询,因此我通过去除句点和下划线来清理占位符 - 因此使用了cleanPlaceholder"变量.

I'm building queries dynamically and therefore I am cleaning the placeholders, by stripping them of periods and underscores - hence the use of the 'cleanPlaceholder' variable.

正在生成的查询如下所示:

The query being generated looks like this:

SELECT * FROM esl_comments WHERE esl_comments.commentVisible=:eslcommentscommentVisible AND esl_comments.commentID=:eslcommentscommentID;

被绑定的参数如下所示:

And the parameters being bound look like this:

eslcommentscommentVisible - Y
eslcommentscommentID - 1

推荐答案

bindParam 需要参考

问题是你在foreach循环中绑定参数的方式造成的.

bindParam Requires a reference

The problem is caused by the way you bind parameters in the foreach loop.

foreach($bindings as $placeholder=>$bound){
    echo $placeholder . " - " . $bound."<br/>";
    $stmt->bindParam($placeholder, $bound);
}

bindParam 需要引用.它将变量而不是值绑定到语句.由于 foreach 循环中的变量在每次迭代开始时重置,因此只有对 $bound 的最后一个引用保持不变,并且您最终将所有占位符绑定到它.

bindParam requires a reference. It binds the variable, not the value, to the statement. Since the variable in a foreach loop is reset at the start of each iteration, only the last reference to $bound is left intact, and you end up binding all your placeholders to it.

这就是为什么您的代码在 $query['where'] 仅包含一个条目时可以工作,但在包含多个条目时失败的原因.

That's why your code works when $query['where'] contains only one entry, but fails when it contains more than one.

您可以通过两种方式解决问题:

You can solve the problem in 2 ways:

foreach($bindings as $placeholder => &$bound) {  //pass $bound as a reference (&)
    $stmt->bindParam($placeholder, $bound);     // bind the variable to the statement
}

传值

使用bindValue代替bindParam:

foreach($bindings as $placeholder => $bound) {  
    $stmt->bindValue($placeholder, $bound);     // bind the value to the statement
}

这篇关于PDO 多个命名占位符不检索数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

The End

相关推荐

PHP实现DeepL翻译API调用
DeepL的翻译效果还是很强大的,如果我们要用php实现DeepL翻译调用,该怎么办呢?以下是代码示例,希望能够帮到需要的朋友。 在这里需要注意,这个DeepL的账户和api申请比较难,不支持中国大陆申请,需要拥有香港或者海外信用卡才行,没账号的话,目前某宝可以...
2025-08-20 php开发问题
168

PHP通过phpspreadsheet导入Excel日期数据处理方法
PHP通过phpspreadsheet导入Excel日期,导入系统后,全部变为了4开头的几位数字,这是为什么呢?原因很简单,将Excel的时间设置问文本,我们就能看到该日期本来的数值,上图对应的数值为: 要怎么解决呢?进行数据转换就行,这里可以封装方法,或者用第三方的...
2024-10-23 php开发问题
287

mediatemple - 无法使用 codeigniter 发送电子邮件
mediatemple - can#39;t send email using codeigniter(mediatemple - 无法使用 codeigniter 发送电子邮件)...
2024-08-23 php开发问题
11

Laravel Gmail 配置错误
Laravel Gmail Configuration Error(Laravel Gmail 配置错误)...
2024-08-23 php开发问题
16

将 PHPMailer 用于 SMTP 的问题
Problem with using PHPMailer for SMTP(将 PHPMailer 用于 SMTP 的问题)...
2024-08-23 php开发问题
4

关于如何在 GoDaddy 服务器中使用 PHPMailer 设置 SMTP 的问题
Issue on how to setup SMTP using PHPMailer in GoDaddy server(关于如何在 GoDaddy 服务器中使用 PHPMailer 设置 SMTP 的问题)...
2024-08-23 php开发问题
17