Ошибка при перезаписи 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' )
and return all rows from the table
WHERE active = 1 AND name = 'James'

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

var_dump( )
is
SELECT * FROM {table} WHERE active = :active AND name = 'James'
- exactly as I expect. The bound parameters prints 'Binding active to 1' and 'Binding name to James' - exactly as expected. The rows exist in the database, and yet the second
var_dump()
call for $results outputs nothing - i.e. no rows are returned.

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

array( 'active' => 1 )
, this works perfectly fine. It appears to be whenever multiple constraints are passed that it stops working.
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
2
0
1 381
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

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

Другие вопросы по теме