2016-09-22 3 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. The: Имя параметра совпадает со значением связывания
  2. Обеспечение число параметров соответствуют значениям PDO в запросе
  3. Binding правильное значение
  4. обеспечения того, чтобы нет нулевых значений

Я знаю, что есть несколько других вопросов относительно этого, но я еще предстоит найти решение этой проблемы. Любая помощь с отладкой очень ценится. Спасибо за чтение.

+1

Помните, что ваш построитель запросов, вероятно, подвержен SQL-инъекции, несмотря на подготовленные операторы. Вы можете проверить мою статью для решения, [SQL-инъекция, против которой подготовленные операторы не помогут] (https://phpdelusions.net/pdo/sql_injection_example) –

ответ

1

Заполнители могут представлять ЦЕННОСТИ. Вы не можете использовать их для 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. Заполнители идеально подходят для данных, но они совершенно бесполезны для многих других запросов.

Смежные вопросы