Ошибка при перезаписи bindParam в PHP

Это немного странно, и я вполне мог бы кодировать это совершенно неправильно – поэтому почему я дважды попадал в ту же ошибку дважды за два дня в совершенно разных частях сценария. Код, который я использую, приведен ниже:

public function findAll( $constraints = array() ) { // Select all records $SQL = 'SELECT * FROM ' . $this->tableName; // See if there's any constraints if( count( $constraints ) > 0 ) { $SQL .= ' WHERE '; foreach( $constraints as $field => $value ) { $SQL .= $field . ' = :' . $field . ' AND '; } } // Remove the final AND and prepare the statement $SQL = substr( $SQL, 0, -5 ); $PDOStatement = $this->PDO->prepare( $SQL ); // Loop through constraints and bind parameters foreach( $constraints as $field => $value ) { print 'Binding ' . $field . ' to ' . $value . ' 
'; $PDOStatement->bindParam( $field, $value ); } $PDOStatement->execute(); var_dump($PDOStatement); while ( $results = $PDOStatement->fetch( PDO::FETCH_ASSOC ) ) { var_dump($results); } }

Я довольно новичок в использовании PDO, но в основном я пытаюсь передать массив ограничений, например

 array( 'active' => 1, 'name' => 'James' ) 

и вернуть все строки из таблицы

 WHERE active = 1 AND name = 'James' 

Если я использую этот массив, SQL выполняется с первого

 var_dump( ) 

является

 SELECT * FROM {table} WHERE active = :active AND name = 'James' 

– точно так, как я ожидаю. Связанные параметры печатают «Binding active to 1» и «Binding name to James» – точно так, как ожидалось. Строки существуют в базе данных, и все же вторая

 var_dump() 

вызов для $ results не выводит ничего, т. е. строки не возвращаются.

Если я передаю массив одного ограничения, например

 array( 'active' => 1 ) 

, это работает отлично. Кажется, что когда передаются несколько ограничений, они перестают работать.

Solutions Collecting From Web of "Ошибка при перезаписи bindParam в PHP"

Это потому, что bindParam работает привязкой к переменной, и вы повторно используете переменную ( $value ) для нескольких значений. bindValue этого bindValue вместо bindValue .

Или еще лучше; Передайте значения как массив для execute вместо этого. Это делает утверждение безстоящим, что обычно хорошо при программировании.

Как уже упоминалось, использование bindValue вместо bindParam , безусловно, выполнит это. Однако, потратив значительное количество времени на устранение этой проблемы в последнее время, я обнаружил альтернативное решение. Вот как выполнить привязку переменной PDO в цикле foreach с помощью bindParam:

Замените следующую строку с исходного сообщения:

 $PDOStatement->bindParam( $field, $value ); 

…с этим:

 $PDOStatement->bindParam( $field, $constraints[$field] ); 

Вместо привязки $value используйте $array_name[$array_key] . Это работает потому, что теперь вы привязываетесь к уникальной переменной, а не к той, которая используется повторно на каждом проходе цикла.

Однако переменное $field используемое в качестве заполнителя, по-видимому, не обязательно должно быть уникальной переменной. Я еще не изучил это до сих пор, но переменная, используемая в качестве заполнителя, как представляется, анализируется немедленно (вместо того, чтобы назначаться как ссылка на переменную) даже при использовании bindParam.

Кроме того, поскольку вам больше не нужно будет напрямую обращаться к $value , вы также можете заменить это:

 foreach( $constraints as $field => $value ) { 

… с этим:

 foreach (array_keys($constraints) as $field) { 

Это необязательно, так как он будет работать нормально без этого изменения. По-моему, это выглядит более чистым, поскольку позже может возникнуть недоумение, почему $value назначено, но никогда не используется.