Intereting Posts

PDO с несколькими именованными заполнителями не извлекает данные

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

Например:

$query = array(); $query['columns'] = array('*'); $query['tables'] = array('esl_comments'); $query['where'] = array( 'esl_comments.commentVisible' => array('=', 'Y') ); 

Работает отлично. Но если я попробую:

 $query = array(); $query['columns'] = array('*'); $query['tables'] = array('esl_comments'); $query['where'] = array( 'esl_comments.commentVisible' => array('=', 'Y'), 'esl_comments.commentID' => array('=', '1'), ); 

(Обратите внимание на дополнительный параметр commentID), он ничего не возвращает, несмотря на наличие данных в базе данных mySQL, которая удовлетворяет условиям.

Код PDO, который я написал, это:

 $sql ='SELECT '; foreach($query['columns'] as $column){ //What columnns do we want to fetch? $sql.=$column . ", "; } $sql = rtrim($sql, " ,"); $sql .=' FROM '; //Which tables will we be accessing? foreach($query['tables'] as $tables){ $sql.=$tables . ", "; } $sql = rtrim($sql, " ,"); //Get rid of the last comma $sql .=' WHERE '; if(array_key_exists('where', $query)) //check if a where clause was provided { $fieldnames = array_keys($query['where']); $count = 0; $size = sizeof($fieldnames); $bindings = array(); foreach($query['where'] as $where){ $cleanPlaceholder = str_replace("_", "", $fieldnames[$count]); $cleanPlaceholder = str_replace(".", "", $cleanPlaceholder); $sql.=$fieldnames[$count].$where[0].":".$cleanPlaceholder." AND "; $bindings[$cleanPlaceholder]=$where[1]; $count++; } $sql = substr($sql, 0, -5); //Remove the last AND } else{ //no where clause so set it to an always true check $sql.='1=1'; $bindings=array('1'=>'1'); //Provide default bindings for the statement } $sql .= ';'; //Add the semi-colon to note the end of the query echo $sql . "<br/><br/>"; // exit(); $stmt = $this->_connection->prepare($sql); foreach($bindings as $placeholder=>$bound){ echo $placeholder . " - " . $bound."<br/>"; $stmt->bindParam($placeholder, $bound); } $result = $stmt->execute(); echo $stmt->rowCount() . " records<br/>"; $results = $stmt->fetchAll(PDO::FETCH_ASSOC); 

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

Создаваемый запрос выглядит следующим образом:

 SELECT * FROM esl_comments WHERE esl_comments.commentVisible=:eslcommentscommentVisible AND esl_comments.commentID=:eslcommentscommentID; 

И связанные с этим параметры выглядят следующим образом:

 eslcommentscommentVisible - Y eslcommentscommentID - 1 

bindParam Требуется ссылка

Проблема связана с тем, как вы привязываете параметры в цикле foreach.

 foreach($bindings as $placeholder=>$bound){ echo $placeholder . " - " . $bound."<br/>"; $stmt->bindParam($placeholder, $bound); } 

bindParam требует ссылки. Он связывает переменную, а не значение, с оператором. Поскольку переменная в цикле foreach сбрасывается в начале каждой итерации, остается только последняя ссылка на $bound , и вы в конечном итоге привязываете к ней все свои заполнители.

Вот почему ваш код работает, когда $query['where'] содержит только одну запись, но сбой, когда он содержит более одного.

Вы можете решить проблему двумя способами:

Передать по ссылке

 foreach($bindings as $placeholder => &$bound) { //pass $bound as a reference (&) $stmt->bindParam($placeholder, $bound); // bind the variable to the statement } 

Передать по значению

Используйте bindValue вместо bindParam :

 foreach($bindings as $placeholder => $bound) { $stmt->bindValue($placeholder, $bound); // bind the value to the statement }