Skip to content

Condicionales y match ​

Los programas útiles toman decisiones: "si el usuario es admin, muestra el panel", "si el stock es cero, muestra Agotado". En esta lección dominarás if, else, elseif, switch y la moderna expresión match, además de la sintaxis alternativa ideal para mezclar PHP con HTML.

Concepto ​

Una condicional es un cruce de caminos: el programa evalúa una pregunta de sí/no y, según la respuesta, sigue un camino u otro. La "pregunta" es cualquier expresión que se pueda convertir en true o false.

if, else, elseif ​

php
<?php
declare(strict_types=1);

$edad = 16;

if ($edad >= 18) {
    echo 'Puedes votar.';
} elseif ($edad >= 16) {
    echo 'Pronto podrás votar.';
} else {
    echo 'Aún eres menor de edad.';
}
  • Las condiciones se evalúan de arriba a abajo y sólo se ejecuta el primer bloque verdadero.
  • else es opcional y atrapa "todo lo demás".
  • Puedes escribir elseif o else if; usa elseif, es lo convencional.

Condiciones combinadas ​

php
<?php
$rol = 'editor';
$activo = true;

if ($activo && ($rol === 'admin' || $rol === 'editor')) {
    echo 'Puedes editar artículos.';
}

// in_array: forma más limpia de comparar contra varias opciones
if ($activo && in_array($rol, ['admin', 'editor'], true)) { // true = comparación estricta
    echo 'Puedes editar artículos.';
}

Retorno temprano (guard clauses) ​

En vez de anidar muchos if, sal en cuanto algo falle. El código queda plano y legible.

php
<?php
function puedeComprar(?array $usuario, int $stock): string
{
    if ($usuario === null) {
        return 'Inicia sesión para comprar.';
    }
    if (!$usuario['verificado']) {
        return 'Verifica tu correo primero.';
    }
    if ($stock === 0) {
        return 'Producto agotado.';
    }
    return 'OK';
}

echo puedeComprar(['verificado' => true], 3); // OK

Compáralo con la versión anidada (difícil de leer):

php
<?php
// MAL: "código flecha", evítalo
if ($usuario !== null) {
    if ($usuario['verificado']) {
        if ($stock > 0) {
            echo 'OK';
        }
    }
}

Sintaxis alternativa para plantillas ​

Cuando mezclas PHP con HTML, las llaves { } se pierden entre etiquetas. PHP ofrece una sintaxis con : y endif; mucho más legible:

php
<?php
$usuario = ['nombre' => 'Carla', 'rol' => 'admin'];
$carrito = [];
?>
<nav>
    <?php if ($usuario): ?>
        <span>Hola, <?= htmlspecialchars($usuario['nombre']) ?></span>
        <?php if ($usuario['rol'] === 'admin'): ?>
            <a href="/admin">Panel</a>
        <?php endif; ?>
        <a href="/logout.php">Salir</a>
    <?php else: ?>
        <a href="/login.php">Iniciar sesión</a>
    <?php endif; ?>
</nav>

<?php if (count($carrito) === 0): ?>
    <p>Tu carrito está vacío.</p>
<?php elseif (count($carrito) === 1): ?>
    <p>Tienes 1 producto.</p>
<?php else: ?>
    <p>Tienes <?= count($carrito) ?> productos.</p>
<?php endif; ?>

Buena práctica

Usa llaves { } en archivos de lógica pura y la sintaxis if: ... endif; en vistas/plantillas HTML. Es la convención que verás en WordPress y en proyectos PHP clásicos.

switch ​

Compara una variable contra varios valores. Útil, pero con trampas.

php
<?php
$dia = 'sábado';

switch ($dia) {
    case 'sábado':
    case 'domingo':        // Varios casos comparten código
        echo 'Fin de semana';
        break;             // ¡Sin break, sigue ejecutando el siguiente case!
    case 'viernes':
        echo 'Casi fin de semana';
        break;
    default:
        echo 'Día laboral';
}

Error común

Olvidar break en un switch. La ejecución "cae" al siguiente case (fall-through) y obtienes resultados raros. Además, switch compara con == (flexible): switch (0) coincide con case 'a' en PHP 7. Por eso, en PHP 8 preferimos match.

match (PHP 8+) ​

match es una expresión: devuelve un valor. Compara con ===, no necesita break y lanza un error si ningún caso coincide (en lugar de fallar en silencio).

php
<?php
declare(strict_types=1);

$estado = 'enviado';

$etiqueta = match ($estado) {
    'pendiente'          => 'Esperando pago',
    'pagado', 'empacado' => 'Preparando tu pedido', // Varios valores separados por coma
    'enviado'            => 'En camino',
    'entregado'          => 'Entregado',
    default              => 'Estado desconocido',
};

echo $etiqueta; // En camino

match sin default ​

php
<?php
$metodo = 'bitcoin';

$comision = match ($metodo) {
    'tarjeta' => 0.035,
    'oxxo'    => 0.02,
};
// UnhandledMatchError: Unhandled match case 'bitcoin'

Esto es bueno: te avisa que olvidaste un caso, en lugar de seguir con un valor incorrecto.

match (true) para rangos ​

Para condiciones complejas, compara contra true: gana el primer brazo cuya condición sea verdadera.

php
<?php
$calificacion = 87;

$letra = match (true) {
    $calificacion >= 90 => 'A',
    $calificacion >= 80 => 'B',
    $calificacion >= 70 => 'C',
    $calificacion >= 60 => 'D',
    default             => 'F',
};

echo $letra; // B

Comparativa ​

switchmatch
Comparación== (flexible)=== (estricta)
Devuelve valorNoSí
Necesita breakSíNo
Sin coincidenciaNo hace nadaLanza UnhandledMatchError
Varias instrucciones por casoSíNo (una expresión por brazo)

Si en un caso necesitas varias instrucciones, usa if o switch, o llama a una función desde el brazo del match.

Ejemplo completo: calculadora de envío ​

php
<?php
declare(strict_types=1);

/**
 * Calcula el costo de envío según la zona y el peso (kg).
 */
function costoEnvio(string $zona, float $peso, float $totalCompra): float
{
    // Envío gratis en compras grandes
    if ($totalCompra >= 1500) {
        return 0;
    }

    $base = match ($zona) {
        'local'    => 60,
        'nacional' => 150,
        'frontera' => 220,
        default    => throw new InvalidArgumentException("Zona no válida: $zona"),
    };

    // Recargo por peso
    $recargo = match (true) {
        $peso <= 1  => 0,
        $peso <= 5  => 50,
        $peso <= 20 => 120,
        default     => 300,
    };

    return $base + $recargo;
}

echo costoEnvio('nacional', 3.2, 900);   // 200
echo '<br>';
echo costoEnvio('local', 0.5, 2000);     // 0

Observa que en PHP 8 throw también es una expresión y puede ir dentro de un match.

Ejercicios ​

  1. Escribe un script que, dado $mes (1 a 12), muestre la estación del año en el hemisferio norte usando match.
  2. Crea una función tipoTriangulo(float $a, float $b, float $c): string que devuelva "Equilátero", "Isósceles" o "Escaleno".
  3. Escribe una plantilla HTML con sintaxis alternativa que muestre un aviso verde si $stock > 10, amarillo si está entre 1 y 10, y rojo "Agotado" si es 0.
Ver solución
php
<?php
declare(strict_types=1);

$mes = 7;

$estacion = match ($mes) {
    12, 1, 2  => 'Invierno',
    3, 4, 5   => 'Primavera',
    6, 7, 8   => 'Verano',
    9, 10, 11 => 'Otoño',
    default   => 'Mes inválido',
};

echo $estacion; // Verano
php
<?php
declare(strict_types=1);

function tipoTriangulo(float $a, float $b, float $c): string
{
    return match (true) {
        $a === $b && $b === $c             => 'Equilátero',
        $a === $b || $b === $c || $a === $c => 'Isósceles',
        default                             => 'Escaleno',
    };
}

echo tipoTriangulo(3, 3, 3); // Equilátero
echo tipoTriangulo(3, 4, 3); // Isósceles
echo tipoTriangulo(3, 4, 5); // Escaleno
php
<?php $stock = 4; ?>
<?php if ($stock > 10): ?>
    <p style="color: green">Disponible</p>
<?php elseif ($stock > 0): ?>
    <p style="color: orange">¡Últimas <?= $stock ?> piezas!</p>
<?php else: ?>
    <p style="color: red">Agotado</p>
<?php endif; ?>

Resumen ​

  • if / elseif / else evalúa de arriba a abajo y ejecuta el primer bloque verdadero.
  • Prefiere retornos tempranos a if anidados.
  • En plantillas usa if: ... elseif: ... else: ... endif;.
  • switch compara con == y necesita break; úsalo con cuidado.
  • match es estricto, devuelve un valor y avisa si falta un caso: tu opción por defecto en PHP 8.
  • match (true) resuelve rangos y condiciones complejas de forma elegante.

Academia Web — aprende, copia y construye.