Search code examples
phppdoprepared-statement

Prepared statement : update only if field is set


I'm trying to update an element in the database using prepared statements.

The table has a lot of fields and only a few of them are submitted in the form

I found out that I can skip the empty fields by setting the value of the field to the field name itself.

UPDATE contacts set name=name, phone_number=phone_number .... WHERE id = 8;

So first I assume that all the fields are submitted;

$query = $db->prepare('UPDATE contacts set name = ?, phone_number = ? WHERE id = ?');

Then I bind each field to its value, depending on wheter its submitted or not

if (isset($name))
{
    $query->bindValue(1, $name);
}
else
{
    $query->bindValue(1, 'name');
}
if (isset($phone_number))
{
    $query->bindValue(2, $phone_number);
}
else
{
    $query->bindValue(2, 'phone_number');
}
$query->bindValue(3, $id);
$query->execute();

For some reason that I'm not aware of, nothing is updated even if the query works in phpmyadmin. However, it only works if all fields are submitted.

UPDATE

I have also tried using named parameters, but it does not seem to work :

$query = $db->prepare('UPDATE contacts set name = :name, phone_number = :phone_number WHERE id = :id');
if (isset($name))
{
    $query->bindValue(':name', $name);
}
else
{
    $query->bindValue(':name', 'name');
}
if (isset($phone_number))
{
    $query->bindValue(':phone_number', $phone_number);
}
else
{
    $query->bindValue(':phone_number', 'phone_number');
}
$query->bindValue(':id', $id);
$query->execute();

OUTPUT

SQL: [77] UPDATE contacts set name = :name, phone_number = :phone_number WHERE id = :id
Params:  3
Key: Name: [5] :name
paramno=-1
name=[5] ":name"
is_param=1
param_type=2
Key: Name: [13] :phone_number
paramno=-1
name=[13] ":phone_number"
is_param=1
param_type=2
Key: Name: [3] :id
paramno=-1
name=[3] ":id"
is_param=1
param_type=2

Solution

  • Since this is my first exeperience with prepared statements in PHP, it took me a long time to realize that we cannot use string laterals directly in bindValue. So the solution was to store the value in a variable just like this :

    $temp = 'name';
    $query->bindValue(':name', $temp);
    

    I hope that someone can explain this behaviour.