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

PDO multiple named placeholders doesnt retrieve data(PDO 多个命名占位符不检索数据)
本文介绍了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 多个命名占位符不检索数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯了您的权益,请联系我们,我们会在确认后第一时间进行删除!

相关文档推荐

DeepL的翻译效果还是很强大的,如果我们要用php实现DeepL翻译调用,该怎么办呢?以下是代码示例,希望能够帮到需要的朋友。 在这里需要注意,这个DeepL的账户和api申请比较难,不支持中国大陆申请,需要拥有香港或者海外信用卡才行,没账号的话,目前某宝可以
PHP通过phpspreadsheet导入Excel日期,导入系统后,全部变为了4开头的几位数字,这是为什么呢?原因很简单,将Excel的时间设置问文本,我们就能看到该日期本来的数值,上图对应的数值为: 要怎么解决呢?进行数据转换就行,这里可以封装方法,或者用第三方的
mediatemple - can#39;t send email using codeigniter(mediatemple - 无法使用 codeigniter 发送电子邮件)
Laravel Gmail Configuration Error(Laravel Gmail 配置错误)
Problem with using PHPMailer for SMTP(将 PHPMailer 用于 SMTP 的问题)
Issue on how to setup SMTP using PHPMailer in GoDaddy server(关于如何在 GoDaddy 服务器中使用 PHPMailer 设置 SMTP 的问题)