I have a routine in my code that computes the differences between two arrays in order create an SQL UPDATE statement.
As soon the routine starts I create a copy of the input array in order to manipulate it while the input one is kept untouched. When I'm ready to create the UPDATE statement I compute the difference between them, using the modified array as leading one.
In every test I ran both arrays were filled with key=value pairs and all values were strings, even when they're integers in the database (PDO behavior) and until now everything worked flawlessly.
But right now I've found something strange. Two different actions, in two different Controllers, but with the same logic are producing different differences:
This one works as expected:
$input = array(
'tid' => '3',
'enabled' => '1'
);
$modified = array(
'tid' => '3',
'enabled' => 0,
'modified' => '2014-11-26 15:17:55'
};
$diff = array(
'enabled' => 0,
'modified' => '2014-11-26 15:17:55'
);
$input is the result of a query. $modified is a copy of the first array manipulated through class methods. When I'm ready to create the statement, $diff is computed in order to send to PDO (or other driver) the correct statement.
Here, array_diff() works. the tid index is present in both array and it's ignored. The enabled, a simple on/off flag, is different and it's included. The datetime representation too.
But look the variables of this other case:
$input2 = array(
'sid' => '1',
'finished' => '0'
);
$modified2 = array(
'sid' => '1',
'finished' => 1,
'modified' => '2014-11-26 15:21:58'
);
$diff2 = array(
'modified' => '2014-11-26 15:21:58'
);
The same as before but with different field names. The sid is ignored but the finished is ignored too while it shouldn't because it is not present in the $input.
By replacing array_diff() with array_diff_assoc(), as expected, everything works, but why?
From the docs:
In your example,
$modified2
has an entry 'finished' which has value 1. But$input2
also has value 1 for key 'sid'. Thus, usingarray_diff($modified2, $input2)
will result in the removal of every entry with value 1, no matter what the key is.Using
array_diff_assoc
, it will only check to see if$input2
has the entry 'finished' => 1, which it does not, so the entry will not be removed.