Вопрос

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


    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'
- именно так, как я ожидаю.Привязанные параметры печатают «Привязка активна к 1» и «Привязка имени к Джеймсу» — точно так, как и ожидалось.Строки существуют в базе данных, но вторая
var_dump()
вызов $results ничего не выводит, т.е.никакие строки не возвращаются.

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

array( 'active' => 1 )
, это прекрасно работает.Кажется, что всякий раз, когда передается несколько ограничений, он перестает работать.

Это было полезно?

Решение

Это потому что bindParam работает путем привязки к переменной, и вы повторно используете переменную ($value) для нескольких значений.Попробуйте с 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 назначается, но никогда не используется.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top