2016-09-22 147 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。占位符是数据的完美选择,但对于其他类型的查询来说,它们完全没有用处。