Cuando una variable puede tener varios valores fijos (un día de la semana, una categoría, un tipo de entrada) y a cada uno le corresponde algo distinto, una cadena de elseif se vuelve larga y repetitiva. Para eso están switch y match.

Incorrecto: una cadena de elseif que repite la misma variable

<?php
$dia = 3;
 
if ($dia === 1) {
    $nombre = "Lunes";
} elseif ($dia === 2) {
    $nombre = "Martes";
} elseif ($dia === 3) {
    $nombre = "Miércoles";
} elseif ($dia === 4) {
    $nombre = "Jueves";
} // … y así hasta el 7

Funciona, pero $dia === se repite en cada línea y lo importante (qué número corresponde a qué nombre) queda escondido.

match

match compara un valor con una lista de opciones y devuelve el resultado de la que coincide.

Anatomía de un match

 $nombre = match ($dia) {
     1 => "Lunes",            <- si $dia === 1, devuelve "Lunes"
     2 => "Martes",
     6, 7 => "Fin de semana", <- varias opciones con el mismo resultado
     default => "Otro día",   <- si ninguna coincide
 };                           <- termina en punto y coma: es una asignación
<?php
$dia = 3;
 
$nombre = match ($dia) {
    1 => "Lunes",
    2 => "Martes",
    3 => "Miércoles",
    4 => "Jueves",
    5 => "Viernes",
    6, 7 => "Fin de semana",
};
 
echo $nombre . "\n";
Miércoles

Correcto: match cuando cada caso es un valor

match es la mejor opción cuando a cada valor le corresponde un resultado: un nombre, un precio, una clase de Tailwind.

<?php
$estado = "pendiente";
 
$color = match ($estado) {
    "aprobado" => "bg-green-100 text-green-800",
    "rechazado" => "bg-red-100 text-red-800",
    "pendiente" => "bg-amber-100 text-amber-800",
};
 
echo "<span class=\"$color\">$estado</span>\n";
<span class="bg-amber-100 text-amber-800">pendiente</span>

Clases de Tailwind: siempre completas

Tailwind no trae el CSS de todas sus clases: genera solo el de las clases que encuentra escritas. Dónde las busca depende de cómo se instaló.

Dónde busca Tailwind las clases

flowchart LR
    subgraph CDN["Tailwind por CDN (el curso)"]
        A1["PHP genera<br/>el HTML"] --> B1["El navegador recibe<br/>class=bg-red-100"] --> C1["Tailwind lee el HTML final<br/>y genera bg-red-100"]
    end
    subgraph COMP["Tailwind compilado (proyectos reales)"]
        A2["Tailwind lee tus archivos<br/>ANTES de que corra PHP"] --> B2["Solo ve el texto<br/>'bg-' . $color . '-100'"] --> C2["No encuentra bg-red-100:<br/>no genera su CSS"]
    end

Con el CDN que usamos (@tailwindcss/browser), Tailwind trabaja en el navegador, sobre el HTML que PHP ya generó: una clase armada por partes funciona, porque cuando Tailwind la lee ya está completa. Pero en un proyecto real Tailwind se compila: revisa tus archivos .php como texto, antes de que PHP se ejecute, y ahí no existe ninguna clase bg-red-100, solo pedazos.

Incorrecto: armar el nombre de la clase con concatenación

<?php
$color = match ($estado) {
    "aprobado" => "green",
    "rechazado" => "red",
    "pendiente" => "amber",
};
?>
<span class="bg-<?= $color ?>-100 text-<?= $color ?>-800"><?= $estado ?></span>

Con el CDN se ve bien, y por eso el error pasa desapercibido. El día que el proyecto use Tailwind compilado, la insignia sale sin color y sin ningún mensaje de error. Además, buscar bg-red-100 en el proyecto no encuentra dónde se usa.

Correcto: match que devuelve las clases completas

<?php
$clases = match ($estado) {
    "aprobado" => "bg-green-100 text-green-800",
    "rechazado" => "bg-red-100 text-red-800",
    "pendiente" => "bg-amber-100 text-amber-800",
};
?>
<span class="<?= $clases ?>"><?= $estado ?></span>

Cada clase aparece escrita entera en el código: funciona con el CDN y compilado, y se puede encontrar con Ctrl + F. La misma regla vale para cualquier clase que elijas con PHP, también con if: $clase = "font-bold text-sky-700";, nunca "text-" . $color . "-700".

match compara con ===

<?php
$opcion = "1";
 
$texto = match ($opcion) {
    1 => "Número uno",
    "1" => "Texto uno",
};
 
echo $texto . "\n";
Texto uno

"1" y 1 son distintos para match, igual que con ===. Recuerda que todo lo que llega de un formulario es texto.

Si ningún caso coincide

Incorrecto: match sin default con un valor inesperado

<?php
$dia = 9;
 
$nombre = match ($dia) {
    1 => "Lunes",
    2 => "Martes",
};
PHP Fatal error:  Uncaught UnhandledMatchError: Unhandled match case 9

Correcto: default cuando el valor puede venir de afuera

<?php
$dia = 9;
 
$nombre = match ($dia) {
    1 => "Lunes",
    2 => "Martes",
    default => "Día no válido",
};
 
echo $nombre . "\n";
Día no válido

match con condiciones: match (true)

Si los casos son rangos y no valores fijos, se escribe match (true) y cada caso es una condición. Gana la primera que da true, igual que en un elseif.

<?php
$nota = 5.5;
 
$concepto = match (true) {
    $nota >= 6.0 => "Excelente",
    $nota >= 5.0 => "Bueno",
    $nota >= 4.0 => "Suficiente",
    default => "Insuficiente",
};
 
echo $concepto . "\n";
Bueno

switch

switch es la forma antigua, la misma de C. Sigue siendo común en código existente, así que hay que reconocerla.

<?php
$dia = 6;
 
switch ($dia) {
    case 1:
    case 3:
        echo "Hay clase de laboratorio\n";
        break;
    case 6:
    case 7:
        echo "Fin de semana\n";
        break;
    default:
        echo "Día normal\n";
}
Fin de semana

Incorrecto: olvidar el break

<?php
$tipo = "estudiante";
 
switch ($tipo) {
    case "estudiante":
        echo "Descuento del 50%\n";
    case "general":
        echo "Precio normal\n";
}
Descuento del 50%
Precio normal

Sin break, switch sigue de largo y ejecuta también los casos de abajo. No da ningún error.

Correcto: un break al final de cada caso

<?php
$tipo = "estudiante";
 
switch ($tipo) {
    case "estudiante":
        echo "Descuento del 50%\n";
        break;
    case "general":
        echo "Precio normal\n";
        break;
}
Descuento del 50%

Cuál usar

SituaciónUsa
Un valor fijo → un resultado (nombre, precio, clase)match
Rangos (>= 6.0, >= 4.0) que devuelven un resultadomatch (true) o if / elseif
Cada caso hace varias cosas (varias instrucciones)if / elseif
Código de otra persona que ya usa switchEntender switch y su break

Diferencias entre switch y match

switchmatch
Compara con== (flexible)=== (estricto)
Devuelve un valorNoSí
Necesita breakSí, en cada casoNo
Si nada coincideNo hace nadaUnhandledMatchError, salvo que tenga default

El operador ??

?? devuelve el valor de la izquierda si existe y no es null; si no, el de la derecha. Sirve para dar un valor por defecto.

<?php
$apodo = null;
echo "Hola, " . ($apodo ?? "invitado") . "\n";
 
$apodo = "Anita";
echo "Hola, " . ($apodo ?? "invitado") . "\n";
Hola, invitado
Hola, Anita

Lo importante: no da Warning si la variable no existe.

Incorrecto: usar algo que puede no existir

<?php
echo "Buscaste: " . $busqueda . "\n";
PHP Warning:  Undefined variable $busqueda in /home/ana/prueba.php on line 2
Buscaste: 

Correcto: ?? con un valor por defecto

<?php
echo "Buscaste: " . ($busqueda ?? "nada") . "\n";
Buscaste: nada

Por qué ?? es tan importante

En la Parte 6 vas a leer datos de la URL, como buscar.php?q=php. Si alguien entra a buscar.php sin el ?q=, ese dato no existe. $_GET["q"] ?? "" es la forma de leerlo sin que aparezca un Warning.

??=: asignar solo si no hay valor

<?php
$titulo = null;
$titulo ??= "Mi sitio";
echo "$titulo\n";
 
$titulo ??= "Otro título";
echo "$titulo\n";
Mi sitio
Mi sitio

$titulo ??= "Mi sitio" es lo mismo que $titulo = $titulo ?? "Mi sitio": solo asigna si $titulo no existía o era null. La segunda vez ya tenía valor y no lo cambió.

Pruébalo

  • Convierte el número del día de la semana (1 a 7) en su nombre con match
  • Clasifica una nota en concepto con match (true)
  • Prueba un match sin default con un valor que no está y lee el error
  • Imprime una variable que no existe con y sin ??, y compara
  • Error provocado: quita un break de un switch y mira qué casos se ejecutan

Errores comunes

SíntomaCausaSolución
Un switch ejecuta varios casosFalta el breakUn break; al final de cada case
UnhandledMatchError: Unhandled match caseNingún caso coincidió y no hay defaultAgrega default =>
match no encuentra un valor que sí estáEl tipo no calza: "1" frente a 1Convierte antes con (int), o escribe el caso como texto
syntax error, unexpected token "}" tras un matchFalta el ; después de la } finalmatch (…) { … };
Una clase de Tailwind armada con PHP no aplica estilo (con Tailwind compilado)El nombre de la clase se armó por partes y Tailwind no lo encontróDevuelve la clase completa desde el match
Undefined variable al leer algo que puede no venirSe usó la variable sin ??$x ?? "defecto"

Checkpoint

Intenta responder antes de desplegar cada pregunta.