Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't array_diff() work straight away with an array of enums, whereas in_array() or array_udiff() do?

Using PHP 8.4, given the following functions:

function test_array_diff($all, $filtered)
{
    return array_diff($all, $filtered);
}
function test_array_udiff($all, $filtered)
{
    return array_udiff($all, $filtered, fn($item1, $item2) => $item1 != $item2);
}
function test_in_array($all, $filtered)
{
    $diff = [];

    foreach ($all as $case) {
        if (!in_array($case, $filtered, true)) {
            $diff[] = $case;
        }
    }

    return $diff;
}

The following enum:

enum MyEnum
{
    case FOO;
    case BAR;
}

And those variables:

$all = MyEnum::cases();
$filtered = [MyEnum::BAR];

Why do subsequent calls work as expected:

var_dump(test_array_udiff($all, $filtered));
var_dump(test_in_array($all, $filtered));

But this one throws:

var_dump(test_array_diff($all, $filtered));

Fatal error: Uncaught Error: Object of class MyEnum could not be converted to string

Shouldn't array_diff() be able to work "out of the box" with enum arrays in the same way as in_array() or array_udiff()?

like image 814
Damien Garrido Avatar asked Apr 29 '26 01:04

Damien Garrido


1 Answers

From the documentation of array_diff():

Two elements are considered equal if and only if (string) $elem1 === (string) $elem2. That is, when the string representation is the same.

Since enums can't be converted to strings, this test is not possible.

The equivalent test_udiff() would be:

function test_array_udiff($all, $filtered)
{
    return array_udiff($all, $filtered, fn($item1, $item2) => (string)$item1 <=> (string)$item2);
}

Note also that you should use the <=> comparison operator. The callback for array_udiff should return a negative, positive, or zero value to indicate the relationship between the values, not a boolean.

like image 156
Barmar Avatar answered May 01 '26 15:05

Barmar



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!