PHP PDO BindParam/BindValue 双引号错误

发布于 2024-12-25 15:50:37 字数 2359 浏览 4 评论 0原文

当尝试将参数绑定到 PDO 准备语句时,我得到了非常令人沮丧的结果。

结果是这个错误: 您的 SQL 语法有错误;检查与您的 MySQL 服务器版本相对应的手册,了解在第 1 行“items”附近使用的正确语法

该错误清楚地表明表“items”在不应该使用单引号的情况下被用单引号引起来是。我在下面做了一个小测试。正如您所看到的,我一开始并没有将参数放在语句中的引号中,这可能是大多数人的最初猜测。我知道它与 BindParam/BindValue (我已经尝试了相同的结果)函数有关,因为如果您通过将 $params 设置为 null 并在语句中将 ':table' 替换为 'items' 来绕过 bindParams 函数,它工作得很好。

<?php

echo 'started test...';

//connect to database

try {
    $dbHandle = new PDO('mysql:dbname=mydatabase;host=mysql.mywebsite.com', 'myuser', 'mypass');   
} catch (PDOException $e) {
    echo 'Database connection failed: ' . $e->getMessage();    
}

//print out the contents of table 'items'

print_r(query("SELECT * FROM :table", array("table" => "items"), $dbHandle));

//the query() function used above

function query($query_str, $params = null, $dbHandle) {

    $stmt_obj = $dbHandle->prepare($query_str);

    if($params != null) {           
        bindParams($stmt_obj, $params);
    }

    $stmt_obj->execute();

    //debug stuff
    echo '<pre>';   
    echo 'ERROR: ';
    $error = $stmt_obj->errorInfo();        
    echo $error[2].'<br /><br />';
    echo 'DEBUG DUMP:<br />';
    $stmt_obj->debugDumpParams();
    echo '</pre>';

    if (preg_match("/SELECT/i", $query_str)) {
        $result = array();      
        while ($row = $stmt_obj->fetch(PDO::FETCH_ASSOC)) {         
            array_push($result, $row);
        }
        unset($stmt_obj);
        return $result;
    }   

}

function bindParams($stmt, $params) {   
    if(is_object($stmt) && ($stmt instanceof PDOStatement))
    {           
        foreach($params as $key => $value)
        {            
            if(is_int($value)) {
                $param = PDO::PARAM_INT; 
            } elseif(is_bool($value)) {
                $param = PDO::PARAM_BOOL;
            } elseif(is_null($value)) {
                $param = PDO::PARAM_NULL;
            } elseif(is_string($value)) {
                $param = PDO::PARAM_STR;
            } else {
                $param = FALSE;
            }
            if($param) {                                                        
                $stmt->bindValue(":$key", $value, $param);                  
            }
        }
    }

有人愿意让我摆脱痛苦并指出我错过的一些非常明显的东西吗?

I'm getting very frustrating results when trying to bind parameters to a PDO prepared statement.

The result is this error:
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 ''items'' at line 1

The error clearly shows that the table 'items' is being quoted with single quotes when it shouldn't be. I've put together a little test below. As you can see, I'm not placing the parameters in quotes in the statement to begin with, which would probably be most people's initial guess. I know it has something to do with the BindParam/BindValue (I've tried both with same results) function because if you bypass the bindParams function by setting $params to null and replacing ':table' with 'items' in the statement, it works perfectly fine.

<?php

echo 'started test...';

//connect to database

try {
    $dbHandle = new PDO('mysql:dbname=mydatabase;host=mysql.mywebsite.com', 'myuser', 'mypass');   
} catch (PDOException $e) {
    echo 'Database connection failed: ' . $e->getMessage();    
}

//print out the contents of table 'items'

print_r(query("SELECT * FROM :table", array("table" => "items"), $dbHandle));

//the query() function used above

function query($query_str, $params = null, $dbHandle) {

    $stmt_obj = $dbHandle->prepare($query_str);

    if($params != null) {           
        bindParams($stmt_obj, $params);
    }

    $stmt_obj->execute();

    //debug stuff
    echo '<pre>';   
    echo 'ERROR: ';
    $error = $stmt_obj->errorInfo();        
    echo $error[2].'<br /><br />';
    echo 'DEBUG DUMP:<br />';
    $stmt_obj->debugDumpParams();
    echo '</pre>';

    if (preg_match("/SELECT/i", $query_str)) {
        $result = array();      
        while ($row = $stmt_obj->fetch(PDO::FETCH_ASSOC)) {         
            array_push($result, $row);
        }
        unset($stmt_obj);
        return $result;
    }   

}

function bindParams($stmt, $params) {   
    if(is_object($stmt) && ($stmt instanceof PDOStatement))
    {           
        foreach($params as $key => $value)
        {            
            if(is_int($value)) {
                $param = PDO::PARAM_INT; 
            } elseif(is_bool($value)) {
                $param = PDO::PARAM_BOOL;
            } elseif(is_null($value)) {
                $param = PDO::PARAM_NULL;
            } elseif(is_string($value)) {
                $param = PDO::PARAM_STR;
            } else {
                $param = FALSE;
            }
            if($param) {                                                        
                $stmt->bindValue(":$key", $value, $param);                  
            }
        }
    }

Anyone care to put me out of my misery and point out something really obvious that I'm missing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

辞旧 2025-01-01 15:50:37

准备好的语句中的符号只是值的占位符,而不是标识符,因此您无法创建具有动态列或表名称的准备好的语句。所有数据库引用都需要在准备时解决。即使这不是真的,PDO/MySQL 如何知道 :table 占位符是文字还是标识符?他们有不同的引用规则。

此限制对于所有数据库系统和所有 API 中的预准备语句都很常见。这肯定不是 PDO bug。

The symbols in prepared statements are only placeholders for values, not identifiers, so you can't create a prepared statement with a dynamic column or table name. All database references need to be resolved at prepare-time. Even if this were not true, how would PDO/MySQL know whether the :table placeholder was meant to be a literal or an identifier? They have different quoting rules.

This restriction is common to prepared statements in all database systems and all APIs. It is certainly not a PDO bug.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文