5

SOLUTION

Change this:

foreach($fields as $dbfield => $field) {
    $value = isset($_POST[$field]) ? 1 : 0;
    $STH -> bindParam( ':' . $dbfield, $value, PDO::PARAM_INT, 1 );
}

to this:

foreach($fields as $dbfield => $field) {
    $value = isset($_POST[$field]) ? 1 : 0;
    $STH -> bindValue( ':' . $dbfield, $value, PDO::PARAM_INT );
}

QUESTION

I have the following code, which doesn't give any errors, but it doesn't do what I need it to do:

PHP

$fields = array(
    'db_col_1'  => 'cb_1',
    'db_col_2'  => 'cb_2',
    'db_col_3'  => 'cb_3'
);

$parts = array();

foreach($fields as $dbfield => $field){
    $parts[] = '`' . $dbfield . '` = :' . $dbfield;
}

$DBH = new PDO( "mysql:host=localhost;dbname=db", "user", "pass" );
$DBH -> setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

//temp id
$id = 1;

$STH = $DBH -> prepare( 'UPDATE `table1` SET ' . join(', ', $parts) . ' WHERE `id`= :id' );

$STH -> bindParam( ':id', $id, PDO::PARAM_INT, 10 );

foreach($fields as $dbfield => $field) {
    $value = isset($_POST[$field]) ? 1 : 0;
    $STH -> bindParam( ':' . $dbfield, $value, PDO::PARAM_INT, 1 );
}

$STH -> execute();

HTML

<input id="cb_1" name="cb_1" type="checkbox" value="cb_1" />
<br />
<input id="cb_2" name="cb_2" type="checkbox" value="cb_2" />
<br />
<input id="cb_3" name="cb_3" type="checkbox" value="cb_3" />

The database goes get updated, but if I check the checkboxes as follows:

SAMPLE CHECKBOX STATES

cb_1 = 1
cb_2 = 1
cb_3 = 0

Every column in the db gets 0.

If I check the checkboxes as follows:

SAMPLE CHECKBOX STATES

cb_1 = 0
cb_2 = 0
cb_3 = 1

Every column in the db gets 1.

Anyone know how to fix this?

Could it be because bindParam binds the actual variable $value (by reference) which I think, by the time the loop ends, has a value based on $_POST['cb_3']?

So I think I am supposed to be using bindValue? But not sure how.. I've checked the documentation, but find it confusing.

oshirowanen
  • 15,297
  • 82
  • 198
  • 350

1 Answers1

16

PDOStatement::bindParam() is a way to tell PDO: «when you execute this statement later, please read the value from this variable». That means that when you call $STH -> execute() the $value must exist and must keep the intended value.

Since you are using it this way:

foreach($fields as $dbfield => $field) {
    $value = isset($_POST[$field]) ? 1 : 0;
    $STH -> bindParam( ':' . $dbfield, $value, PDO::PARAM_INT, 1 );
}

... $value gets overwritten on each loop iteration and your values get lost. (Only the last one remains.)

You need to use PDOStatement::bindValue() that means: «store this value and use it later when you execute the statement». This way, the variable is no longer necessary.

Álvaro González
  • 142,137
  • 41
  • 261
  • 360