2016-09-22 149 views
0

我在寫一個API類來查詢數據。我有一個使用SELECT語句查詢特定硬編碼表名稱(即eventLog)的數據的函數。綁定參數值 - PDO無效參數編號

查詢列表如下,其中:value引用傳遞給函數paremeter:

// 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. 的:參數名稱綁定值
  2. 匹配確保參數號匹配查詢
  3. 綁定正確的值
  4. 確保PDO值有沒有空值

我知道還有幾個其他問題,但我還沒有找到解決這個問題的方法。任何幫助調試非常感謝。謝謝你的閱讀。

+1

請記住,儘管已準備好語句,但您的查詢構建器很可能傾向於SQL注入。您可以查看我的文章以獲得解決方案,[準備好的語句無法幫助的SQL注入](https://phpdelusions.net/pdo/sql_injection_example) –

回答

1

佔位符只能代表VALUES。您不能將它們用於SQL關鍵字/標識符。

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

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

您還可以報價佔位符。一旦他們被引用,他們不再是佔位符,他們是字面上的字符串。

如果要插入之類的話dynmamically,你必須建立自己的查詢字符串:

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

是的,這讓你開到潛在sql injection attacks。佔位符是數據的完美選擇,但對於其他類型的查詢來說,它們完全沒有用處。