match en PHP 8: la alternativa al switch sin comparación débil ni fall-through

La expresión match de PHP 8 es una alternativa mejorada a switch con tres diferencias clave: usa comparación estricta (===), no tiene fall-through implícito entre casos y devuelve un valor directamente. También lanza UnhandledMatchError si ningún caso coincide, lo que evita errores silenciosos.

match vs switch: diferencias básicas

<?php
$codigo = 200;

// Con switch: comparación débil, fall-through, no devuelve valor
switch ($codigo) {
    case 200:
        $msg = 'OK';
        break;
    case 404:
        $msg = 'No encontrado';
        break;
    default:
        $msg = 'Desconocido';
}

// Con match: comparación estricta, devuelve valor directamente
$mensaje = match ($codigo) {
    200 => 'OK',
    301, 302 => 'Redirección',
    404 => 'No encontrado',
    500 => 'Error del servidor',
    default => 'Código desconocido',
};

echo $mensaje; // OK
?>

Comparación estricta: la gran diferencia con switch

<?php
$valor = '0';

// switch con comparación débil: '0' == false es true en PHP
switch ($valor) {
    case false:
        echo 'switch: falsy';   // ? esto se ejecuta (¡incorrecto!)
        break;
    case '0':
        echo 'switch: cero';
        break;
}

// match con comparación estricta: '0' !== false
$resultado = match ($valor) {
    false => 'match: falsy',
    '0'   => 'match: cero',  // ? esto se ejecuta (correcto)
    default => 'otro',
};

echo $resultado; // match: cero
?>

UnhandledMatchError: sin silencio cuando no hay caso

<?php
function descripcionMetodo(string $metodo): string
{
    return match ($metodo) {
        'GET'    => 'Obtener recurso',
        'POST'   => 'Crear recurso',
        'PUT'    => 'Reemplazar recurso',
        'PATCH'  => 'Modificar parcialmente',
        'DELETE' => 'Eliminar recurso',
    };
    // Si $metodo es 'OPTIONS' u otro valor no listado,
    // lanza UnhandledMatchError automáticamente
}

try {
    echo descripcionMetodo('OPTIONS');
} catch (UnhandledMatchError $e) {
    echo 'Método HTTP no reconocido';
}
?>

Ejemplos reales: roles y permisos

<?php
enum Rol: string
{
    case Admin   = 'admin';
    case Editor  = 'editor';
    case Lector  = 'lector';
}

function nivelAcceso(Rol $rol): int
{
    return match ($rol) {
        Rol::Admin  => 3,
        Rol::Editor => 2,
        Rol::Lector => 1,
    };
}

echo nivelAcceso(Rol::Editor); // 2
?>

Rangos y condiciones en match (PHP 8.0+)

<?php
function categoriaPrecio(float $precio): string
{
    return match (true) {
        $precio < 10             => 'Muy barato',
        $precio < 50             => 'Económico',
        $precio < 200            => 'Precio medio',
        $precio < 1000           => 'Premium',
        default                  => 'Lujo',
    };
}

echo categoriaPrecio(7.5);   // Muy barato
echo categoriaPrecio(89.0);  // Precio medio
echo categoriaPrecio(2500.0); // Lujo
?>

match para tipos MIME

<?php
function extensionDesdeContentType(string $contentType): string
{
    return match ($contentType) {
        'image/jpeg'               => 'jpg',
        'image/png'                => 'png',
        'image/webp'               => 'webp',
        'application/pdf'          => 'pdf',
        'text/plain'               => 'txt',
        'application/json'         => 'json',
        'application/octet-stream' => 'bin',
        default                    => 'dat',
    };
}

echo extensionDesdeContentType('image/png');  // png
echo extensionDesdeContentType('text/plain'); // txt
?>

La documentación oficial de match en PHP detalla la precedencia de los brazos del match, la combinación de múltiples condiciones por caso y cómo se comporta con no-arms y el default.

COMPARTE ESTE ARTÍCULO

COMPARTIR EN FACEBOOK
COMPARTIR EN TWITTER
COMPARTIR EN LINKEDIN
COMPARTIR EN WHATSAPP