警告:mysqli::bind_param():动态赋值变量时,变量数量与预置语句中的参数数量不匹配


Warning: mysqli::bind_param(): Number of variables doesn't match number of parameters in prepared statement when assigning variables dynamically

我目前正在寻找使用API安全地连接和管理查询(SQL注入缓解)的方法,同时尝试遵循DRY指南。我使用准备好的语句来防止SQL注入,但是在运行接收到HTTP GET请求时调用的函数时,我遇到了警告:

警告:mysqli::bind_param():变量的数量不匹配参数的数量在准备语句…

然后我的查询失败:

错误:command out of sync;你现在不能运行这个命令Errno 2014

一个简单的谷歌搜索给了我这个答案:

如果你得到命令不同步;你现在不能在你的客户端代码中运行这个命令,你调用客户端函数的顺序错了。

警告和错误消息仅在数组中有多个参数时发生。我的mySQL查询函数如下:

    //set properties to values given by constructor params, 
    //open mysqli connection, etc..
    public function query_db_stmt($sql, $param)
    {
        $stmt = $this->connection->prepare($sql);
        for ($i = 1; $i < count($param); ++$i)
        {
            $stmt->bind_param(($param[0][$i - 1]), $param[$i]);  
        }
        $stmt->execute();
        $result = $stmt->get_result();
        $stmt->close();
        return $result;
    } // do other stuff here, like close the sql connection in __destruct()...

然后创建对象,然后像这样调用查询函数:

$sql = 'SELECT ? FROM user WHERE id=?;';
$result = $mysql_db->query_db_stmt($sql, array('si', '*', $this->args[0]));  

我显然做错了什么,因为我得到这些警告,和一个错误的数字2014,但我不知道它是什么。如有任何帮助,不胜感激。

编辑:

我现在明白我不能使用列名或表名作为预处理语句,但是在使用此代码时,除了HTTP PUT请求之外,我仍然有类似的问题:

    parse_str(file_get_contents("php://input"), $put_vars);
    $sql = 'INSERT INTO user (username, password, email, birth, sex) VALUES (?, ?, ?, ?, ?);';
    $mysql_db->query_db_stmt($sql, array('sssss', $put_vars['username'], password_hash($put_vars['password'], PASSWORD_DEFAULT), 
      $put_vars['email'], $put_vars['birth'], $put_vars['sex']));

使用curl,我运行curl -X PUT http://localhost/r.php -d username=foo -d password=boo -d email=test@gmail.com -d birthday=2015-08-13 -d sex=m

我得到相同的错误5次:

警告:mysqli::bind_param():变量的数量不匹配参数的数量在准备语句…

如前所述,But no DB Query failed错误。任何评论?

问题是您试图在PDO中绑定表名。PDO中不能替换表名和列名

您不需要将列名放在?中并准备语句。相反,只需将语句的值作为参数并将变量绑定到它们。所以$sql应该是-

$sql = 'SELECT * FROM user WHERE id=?';

然后相应地绑定变量。

另外,不要在查询中使用SELECT *,总是指定您想要输出的列名。