【问题标题】:Binding parameter values - PDO Invalid parameter number绑定参数值 - PDO 参数号无效
【发布时间】:2017-01-31 04:07:50
【问题描述】:

我正在编写一个 API 类来查询数据。我在类中有一个函数,它使用 SELECT 语句来查询特定硬编码表名(即 eventLog)的数据。

下面列出了查询,其中:value 引用了传递给函数的参数:

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

我正在尝试使用 PDO 语句来防止 SQL 注入。我已经阅读了一些关于如何正确编写 PDO 语句的有用文档,包括 bindValue / bindParam。

以下是完整的类文件:

<?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);
        }
    }

?>

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 />
[]

所以,基于这个执行,绑定的 SQL 查询应该是:

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

但是,我收到错误消息:Invalid parameter number: parameter was not defined

我已经检查了以下内容:

  1. :parameter 名称与绑定值匹配
  2. 确保参数编号与查询中的 PDO 值匹配
  3. 绑定正确的值
  4. 确保没有空值

我知道还有其他几个关于此问题的问题,但我还没有找到解决此问题的方法。非常感谢任何有关调试的帮助。感谢您的阅读。

【问题讨论】:

标签: php pdo


【解决方案1】:

占位符只能代表VALUES。您不能将它们用于 SQL 关键字/标识符。

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

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

您也可以引用占位符。一旦被引用,它们就不再是占位符,而是文字字符串。

如果你想动态插入这种东西,你必须自己构建查询字符串:

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

是的,这让你对潜在的sql injection attacks 敞开大门。占位符非常适合数据,但对于许多其他类型的查询完全没用。

【讨论】:

    猜你喜欢
    • 2015-05-11
    • 2016-03-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-15
    相关资源
    最近更新 更多