Why does PHP array_diff work this way

I tried to filter the date from the form down to what the user changed and started using array_filter, as this seemed to do exactly what I wanted. I checked several forms and came across this unexpected behavior. When the "new" value is 1, it is not determined array_diff. Also unexpected when launching this on 3v4l.org was that the foreach loop was actually faster than array_filterreturning the expected result. I read the man-page for functions and realized that it is comparing strings, but all array values ​​start with strings. I would not expect this to be a type conversion problem.

I have solved my initial problem and will happily use the faster foreach loop, but I wonder if anyone can explain why this works this way.

https://3v4l.org/1JggJ

<?php

$array_1 = [
    'id' => '42',
    'base_id' => '23',
    'role_id' => '1',
    'title' => 'Manage Account',
    'slug' => 'manage_account',
    'parent' => '31',
    'order' => '1',
    'visibility' => '1'
];
$array_2 = [
    'id' => '42',
    'base_id' => '23',
    'role_id' => '99999',
    'title' => 'Manage Account',
    'slug' => 'manage_account',
    'parent' => '31',
    'order' => '1',
    'visibility' => '1'
];

var_dump(array_diff($array_1, $array_2));
// Result (unexpected)
// array (size=0)
//   empty        

$diff = [];
foreach ($array_1 as $key => $value) {
    if ((string) $array_1[$key] !== (string) $array_2[$key]) {
        $diff[$key] = $value;
    }
}

var_dump($diff);
// Result (expected)
// array (size=1)
//   'role_id' => string '1' (length=1)
+4
source share
1 answer

array_diff() looks for exact duplicates for each value of array 1 in array 2, ignoring the keys.

1has a duplicate in array 2, for example. under the key order. That is why it is not indicated as a difference.

whether this behavior is optimal or obvious is controversial, but how it works.


If you change 1to a 3, this will be reported, since array 2 does not contain a value 3:

    $array_1 = [
        'id' => '42',
        'base_id' => '23',
        'role_id' => '3',
        'title' => 'Manage Account',
        'slug' => 'manage_account',
        'parent' => '31',
        'order' => '1',
        'visibility' => '1'
    ];
    $array_2 = [
        'id' => '42',
        'base_id' => '23',
        'role_id' => '99999',
        'title' => 'Manage Account',
        'slug' => 'manage_account',
        'parent' => '31',
        'order' => '1',
        'visibility' => '1'
    ];

    var_dump(array_diff($array_1, $array_2));
    // Result (unexpected)
    // array (size=1)
    //   'role_id' => string '3' (length=1)  

If you want the keys to be taken into account, use array_diff_assoc().

+5
source

Source: https://habr.com/ru/post/1692892/


All Articles