Using an Array of values with a Match Expression in PHP

Viewed 496

Is there a way to use an array as a list of values to match against in a match expression in PHP?

Consider this:

return match ($field) {
    'id', 'first_name', 'last_name', 'updated_at', 'created_at' => (string) $item->{$field},
    'image' => $item->{$field}->getUrls(),
    'balance' => (int) $item->{$field},
    default => null
};

Whilst the above works, I would like to format the match statement in a more readable/manageable manner. For instance, I use the above expression on my data transformers for presenting data in my APIs; as such, I can find myself in situations where there are many fields returned in one format, and it would be significantly more readable to present it in the following manner (or something similar):

$string_columns = ['id', 'first_name', 'last_name', 'updated_at', 'created_at'];

return match ($field) {
    $string_columns => (string) $item->{$field},
    'image'         => $item->{$field}->getUrls(),
    'balance'       => (int) $item->{$field},
    default         => null
};
2 Answers

Your question inspired me to check if ...$string_columns would work for match statement, but it doesn't.

I don't think there's any way to do it with match, other than tricks.

One trick I thought of was to create a helper function to return the value only if it's in the array:

function any(array $values, $value)
{
    return in_array($value, $values, true) ? $value : null;
}

$string_columns = ['id', 'first_name', 'last_name', 'updated_at', 'created_at'];

return match ($field) {
    any($string_columns, $field) => (string) $item->{$field},
    'image'                      => $item->{$field}->getUrls(),
    'balance'                    => (int) $item->{$field},
    default                      => null
};

A bit verbose, but would work.

I think it's worth to understand match as a language construction that suits only certain scenarios.

It is not posible. Just add in_array in default value.

return match ($field) {
    'image'         => $item->{$field}->getUrls(),
    'balance'       => (int) $item->{$field},
    default => in_array($value, $string_columns, true) ? 
              (string) $item->{$field} 
              : null;
};

If there will be more arrays, you can chain ternary operator

Related