简体   繁体   English

绑定参数值-PDO无效的参数号

[英]Binding parameter values - PDO Invalid parameter number

I'm writing an API class to query data. 我正在编写一个API类来查询数据。 I have a function in the class that uses a SELECT statement to query data for a specific, hardcoded table name (ie eventLog). 我在类中有一个函数,该函数使用SELECT语句查询数据以获取特定的硬编码表名(即eventLog)。

The query is listed below, where :value references a paremeter passed to the function: 该查询在下面列出,其中:value引用传递给该函数的参数:

// query
$sql = "SELECT :selectType 
        FROM  `log` :clause
        ORDER BY `:orderByColumn` :orderByClause
        LIMIT :limitStart, :limitStep";

I'm trying to use PDO statements to prevent SQL injection. 我正在尝试使用PDO语句来防止SQL注入。 I have read several helpful documents regarding how to correctly write PDO statements, including bindValue / bindParam. 我已经阅读了一些有关如何正确编写PDO语句的有用文档,包括bindValue / bindParam。

Below is the full class file: 下面是完整的类文件:

<?php

    // set requirements
    require_once 'Database.php';

    /*  EventLogsAPI class
    *  This class is used to query data from the eventLog table, and handle other data processing
    */
    class EventLogsAPI {

        // set class member variables
        private $connection;    // database connection
        private $records;       // records from query

        /*  Constructor function
        */
        public function __construct() {
              // create DB object
              $this->connection = new DBConnection();
        }

        /*  Collect records function
         *  Get the records from this prep statement, and store them in $this->records
         * 
         *  @param object - database object
        */
        public function collectRecords($prep) {
              // clear records from previous query
              $this->records = array();

              // execute query 
              $prep->execute();

              // for each record
              while (false !== ($row = $prep->fetch(PDO::FETCH_ASSOC))) {
                    $this->records[] = $row;
              }
        }

        /*  getEventLogData function 
         *  Get event log data with a optional (where) clause
         *
         *  @param string - select state (*, distinct, etc...)
         *  @param string - conditional SQL clause (e.g. where ID = 2)
         *  @param string - order by column (e.g. user, ID, date, etc...)
         *  @param string - order by clause (e.g. asc, desc)
         *  @param integer - starting limit param (i.e. 0)
         *  @param integer - limit step param (i.e. 25)
         *  @param boolean - used to debug SQL
         *  @return JSON - json containing array of records
        */
       public function getEventLogData($selectType, $clause, $orderByColumn, $orderByClause, $limitStart, $limitStep) {

              // query
              $sql = "SELECT :selectType 
                      FROM  `log` :clause
                      ORDER BY `:orderByColumn` :orderByClause
                      LIMIT :limitStart, :limitStep";

              // prep the query
              $prep = $this->connection->DB('log')->prepare($sql);

              // for each function argument 
              foreach ($bind = func_get_args() as $key => $value) {
                    // prevent null values
                    if ($value == NULL) {
                          // set to empty strings
                          $bind[$key] = "";
                    }

                    // bind value
                    $prep->bindValue(":$bind[$key]", $bind[$key]); 

                    // debug
                    echo ($key . " - " . $value . "\n");
              }

              // collect the records
              $this->collectRecords($prep);            
              // return records
              return json_encode($this->records);
        }
    }

?>

Returned network response in Chrome console: 在Chrome控制台中返回的网络响应:

0 - *
1 - 
2 - date
3 - DESC
4 - 0
5 - 20
<br />
<b>Warning</b>:  PDOStatement::execute(): SQLSTATE[HY093]: Invalid parameter number: parameter was not defined in <b>EventLogsAPI.class.php</b> on line <b>32</b><br />
[]

So, based on this execution, the bound SQL query should be: 因此,基于此执行,绑定的SQL查询为:

// query
$sql = "SELECT * 
        FROM  `log` 
        ORDER BY `date` DESC
        LIMIT 0, 20";

However, I'm getting the error: Invalid parameter number: parameter was not defined . 但是,我得到了错误: Invalid parameter number: parameter was not defined

I have checked the following: 我检查了以下内容:

  1. The :parameter name matches the bind value :parameter名称与绑定值匹配
  2. Ensuring the parameter number matches the PDO values in the query 确保参数编号与查询中的PDO值匹配
  3. Binding the correct value 绑定正确的值
  4. Ensuring that there are no null values 确保没有空值

I know there are several other questions regarding this, but I have yet to find a solution to this problem. 我知道与此有关的还有其他几个问题,但是我还没有找到解决这个问题的方法。 Any help with debugging is much appreciated. 非常感谢调试方面的任何帮助。 Thank you for reading. 感谢您的阅读。

Placeholders can represent VALUES only. 占位符只能代表VALUES You cannot use them for SQL keywords/identifiers. 您不能将它们用于SQL关键字/标识符。

    FROM  `eventLog` :clause
                       ^--keyword/identifier

    ORDER BY `:orderByColumn` :orderByClause
             ^--------------^--- also wrong

You also can NOT quote placeholders. 您也不能引用占位符。 Once they're quoted, they're not placeholders anymore, they're literal strings. 一旦被引用,它们就不再是占位符,它们是文字字符串。

If you want to insert that kind of thing dynmamically, you have to build the query string yourself: 如果要动态插入这种内容,则必须自己构建查询字符串:

$order_by = 'ASC':
$sql = "SELECT ... ORDER BY $order_by";

And yes, this leaves you open to potential sql injection attacks . 是的,这使您容易受到潜在的sql注入攻击 Placeholders are perfect for data, but they're utterly useless for many other kinds of queries. 占位符是数据的完美选择,但对于许多其他类型的查询却毫无用处。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM