skip to Main Content

Let’s say I have an enum like this:

enum Shippint: string
{
    case Express = 'express';
    case Standard = 'standard';
    case Economy = 'cheap';

    /** @return string[] */
    public static function values(): array
    {
        return array_column(self::cases(), 'value');
    }
}

and I have 2 arrays that I want to compare and do something similar to array_diff

$arr1 = [
   Delivery::tryFrom('express')
   Delivery::tryFrom('cheap')
];
$arra2 = [
   Delivery::tryFrom('express')
   Delivery::tryFrom('standard')
]

I can loop through and convert each enums array to an array of strings

$arrOfStrings1 = [];
$arrayOfStrings2 = [];

foreach($arr1 as $value) {
   $arrOfStrings1[] = $value->value;
}

foreach($arr2 as $value) {
   $arrayOfStrings2[] = $value->value;
}

if (array_diff($arrOfStrings1, $arrayOfStrings2)) {
    echo 'arrays different';
} else {
    echo 'same'
}

I can hide this inside the enums methods, but still, maybe there is some built-in PHP way to do it? Unfortunately, it’s impossible to add __toSting() to enums otherwise it’ll be possible to do array_diff as it automatically converts objects to strings. Thanks

2

Answers


  1. You can use array_udiff:

    if (array_udiff($arr1, $array2, fn ($a, $b) => $a->value <=> $b->value))) {
        echo 'arrays different';
    } else {
        echo 'same'
    }
    
    Login or Signup to reply.
  2. I know that people will probably hate me for this answer, but still, I’m going to write it.
    You can use __toString() method inside an enum, and let me tell you how.
    If you try to define a __toString() method inside your enum, you will get an error that looks similar to:

    PHP Fatal error: Enum Delivery cannot include magic method __toString

    The check for the existence of __toString() method happens during compile-time, but not during runtime. So all we need to do is to find a way to define this method during runtime, and that’s where the UOPZ extension comes into play.

    The UOPZ extension defines a uopz_add_function() function which you can use to achieve this, here’s an example:

    enum Delivery: string {
        case Express = 'express';
        case Standard = 'standard';
        case Economy = 'cheap';
    
        /** @return string[] */
        public static function values() : array
        {
            return array_column(self::cases(), 'value');
        }
    
    }
    
    
    uopz_add_function(Delivery::class, "__toString", fn() => $this->value); // <-- THE MAGIC LINE
    
    $arr1 = [
        Delivery::tryFrom('cheap'),
        Delivery::tryFrom('standard')
    ];
    
    $arr2 = [
        Delivery::tryFrom('express'),
        Delivery::tryFrom('standard')
    ];
    
    if (array_diff($arr1, $arr2)) {
        echo 'arrays different';
    } else {
        echo 'same';
    }
    

    This code works perfectly fine. This extension is very powerful for these kinds of issues.

    More information on the function here: https://www.php.net/manual/en/function.uopz-add-function.php

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search