0

PHP PDO show some inexplicable behaviour. The parameter placeholders are replaced with the same values.

$query

UPDATE `newsletters` SET `title` = :title , `scheduled` = :scheduled , `modified` = :modified WHERE `id` = :id

$parameter

Array
(
    [:title] => New Newsletter22
    [:scheduled] => 2013-04-15 21:47:00
    [:modified] => 2013-04-15 21:47:51
    [:id] => 35
)

The Function

public  static function execute($query=null,$parameters=array())
{
    global $dbnew;

    $statement= $dbnew->prepare($query);


        foreach($parameters as $k=>$v){
            if(is_array($v)){
                $statement->bindParam($k, $v[0],$v[1]);
            }else{
                $statement->bindParam($k, $v);
            }
        }


    $statement->execute();
    return $statement;
}

Executed query

1132 Query  UPDATE `newsletters` SET `title` = '35' , `scheduled` = '35' , `modified` = '35' WHERE `id` = '35'
ynh
  • 2,919
  • 1
  • 19
  • 18
  • 7
    You may want to use `bindValue` instead of `bindParam`. Your foreach loop is overwriting the value of $v upon each iteration. More info here: http://stackoverflow.com/questions/1179874/pdo-bindparam-versus-bindvalue – showdev Apr 15 '13 at 21:58
  • Yes, or pushing the values into an array. – Jonast92 Apr 15 '13 at 22:00
  • 1
    Whenever something looks inexplicable to me in my PHP code, I more or less automatically go to the function/method page in the manual and double check all parameter, return-types, notes, warnings and user-comments. Most often then it's a short A-HA! and then back to coding. – M8R-1jmw5r Apr 15 '13 at 22:01
  • @showdev Post that as an answer. – Barmar Apr 15 '13 at 22:18

1 Answers1

2

The bindParam method binds a reference to a variable, rather than the value of the variable.

Your foreach loop updates the value of $v upon each iteration.

Since bindParam doesn't bind values until you actually execute the query, the value of all bound parameters in your example will be the same. They will all be bound to the value of $v from your last loop iteration.

Use bindValue to bind the actual value of the variable rather than a reference.

$statement->bindValue($k, $v);

From php.net documentation:

bool PDOStatement::bindParam
Binds a PHP variable to a corresponding named or question mark placeholder in the SQL statement that was used to prepare the statement. Unlike PDOStatement::bindValue(), the variable is bound as a reference and will only be evaluated at the time that PDOStatement::execute() is called.

showdev
  • 28,454
  • 37
  • 55
  • 73