Ошибка с перезаписью bindParam в PHP - PullRequest
2 голосов
/ 29 сентября 2008

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


    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 . ' <br />';
            $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 )
, это прекрасно работает. Кажется, что когда передается несколько ограничений, он перестает работать.

Ответы [ 2 ]

10 голосов
/ 29 сентября 2008

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

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

0 голосов
/ 26 декабря 2014

Как уже упоминалось, использование 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 назначается, но никогда не используется.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...