Asked  7 Months ago    Answers:  5   Viewed   27 times

I had a loop like that :

foreach($Fields as $Name => $Value){
    $Query->bindParam(':'.$Name, $Value, PDO::PARAM_STR);
}

Nothing complicated. However, each value was set to the last one in the array ($Fields).

How can I fix that ?

 Answers

85

However, thanks to this guys. I found out that you need to pass the value by reference with a & before like that :

foreach($Fields as $Name => &$Value){
    $Query->bindParam(':'.$Name, $Value, PDO::PARAM_STR);
}

This was driving me nuts.

Actual quote from PHP.net :

Vili 28-May-2010 12:01

This works ($val by reference):

<?php
foreach ($params as $key => &$val){
    $sth->bindParam($key, $val);
}
?>

This will fail ($val by value, because bindParam needs &$variable):

<?php
foreach ($params as $key => $val) {
    $sth->bindParam($key, $val);
}
?>
Wednesday, March 31, 2021
 
Hugo
answered 7 Months ago
74

Trying to bindParam to an array element like $array['key'] causes a few issues because its bound as reference, but its not. Its, just not done that way.

So three ways:

$stmt = $dbh->prepare($sql);
// bind to variables that can be a reference
$stmt->bindParam(":GROUP_ID", $id, PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_1", $pt1, PDO::PARAM_INT);
$stmt->bindParam(":INSTALLED_VERSION_NUM_2", $pt2, PDO::PARAM_INT);
foreach ($installed_groups as $installed_group){
        $installed_version_parts = explode('.', $installed_group['version']);
        // assign the referenced vars their new value before execute
        $id = $installed_group['group_id'];
        $pt1 = $installed_version_parts[1];
        $pt2 = $installed_version_parts[2];
        $stmt->execute();
}

Or: (less efficient)

$stmt = $dbh->prepare($sql);
foreach ($installed_groups as $installed_group){
        $installed_version_parts = explode('.', $installed_group['version']);

        // use bindValue (not bindParam) INSIDE the loop
        // bindValue doesn't set them by reference, so any value expression works
        $stmt->bindValue(":GROUP_ID", $installed_group['group_id'], PDO::PARAM_INT);
        $stmt->bindValue(":INSTALLED_VERSION_NUM_1", $installed_version_parts[1], PDO::PARAM_INT);
        $stmt->bindValue(":INSTALLED_VERSION_NUM_2", $installed_version_parts[2], PDO::PARAM_INT);
        $stmt->execute();
}

Or:

$stmt = $dbh->prepare($sql);
foreach ($installed_groups as $installed_group){
        $installed_version_parts = explode('.', $installed_group['version']);

        // pass them on execute directly
        $stmt->execute(array(':GROUP_ID'=>$installed_group['group_id'],
                             ':INSTALLED_VERSION_NUM_1'=>$installed_version_parts[1],
                             ':INSTALLED_VERSION_NUM_2'=>$installed_version_parts[2]));
}
Wednesday, March 31, 2021
 
Fredy
answered 7 Months ago
42

Had already downloaded the driver and it didn't work. Found a new site for the driver and this one works.

https://github.com/Microsoft/msphpsql/releases

php.ini line added:

extension=php_pdo_sqlsrv_7_nts.dll
Wednesday, March 31, 2021
 
njai
answered 7 Months ago
73

showdev's comment is correct that the PDO DSN does not allow host:port syntax.

If your CMS is defining DB_HOST outside of your control, you can't use that constant directly. But you can pull information out of it.

$host_port = preg_replace('/:(d+)/', ';port=${1}', DB_HOST);
$db = new PDO("mysql:host={$host_port};dbname=".DB_NAME.";charset=utf8", 
    DB_USER, DB_PW, array(PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8"));
Friday, May 28, 2021
 
Chvanikoff
answered 5 Months ago
90

use bindValue() instead of bindParam(). bindParam() binds to a reference, so when you execute the query all the parameters use the last value of $val.

Tuesday, August 10, 2021
 
Anton Barinov
answered 2 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :