Saltar a contenido

CONTROL DE FLUJO EN PHP

Estos apuntes son material de consulta para el Lab 04. Cubren los conceptos que vas a aplicar allí: condicionales if / elseif / else, operadores de comparación y lógicos, la expresión match, el operador ?? para leer parámetros de la URL, y el patrón de filtrar con if dentro de un foreach.

Condicionales con if

Sintaxis básica

Un if ejecuta un bloque de código solo si una condición se cumple:

if (condición) {
    ## se ejecuta si condición es true
} elseif (otra_condición) {
    ## se ejecuta si la primera es false y esta es true
} else {
    ## se ejecuta si todas las anteriores son false
}

PHP evalúa las condiciones en orden y ejecuta solo el primer bloque cuya condición sea verdadera. El resto se salta.

Comparación con bash:

Bash PHP
if [ "$estado" = "abierta" ]; then if ($estado === 'abierta') {
elif elseif
fi } (o endif; en sintaxis alternativa)

Operadores de comparación

Operador Significado Ejemplo
=== Igualdad estricta (mismo tipo y mismo valor) $p === 'alta'
!== Desigualdad estricta $p !== 'baja'
<, > Menor / mayor que $n < 5
<=, >= Menor o igual / mayor o igual $n >= 0

En este proyecto se usa siempre === y !==, no == y !=. La razón es que == hace conversiones automáticas de tipo que pueden dar resultados sorprendentes (por ejemplo, 0 == 'texto' es true). Con === lo que escribes es exactamente lo que se compara.

Operadores lógicos

Para combinar varias condiciones:

$es_alta      = $prioridad === 'alta';
$es_pendiente = $estado === 'pendiente';

## Las dos a la vez:
if ($es_alta && $es_pendiente) { ... }

## Al menos una:
if ($es_alta || $es_pendiente) { ... }

## Negación:
if (!$resuelto) { ... }
Operador Bash Significado
&& && Y lógico
\|\| \|\| O lógico
! ! Negación

Sintaxis alternativa dentro de HTML

Igual que con foreach del Lab 03, dentro de plantillas HTML usamos la forma con : / endif en lugar de llaves. Se lee mucho mejor cuando el cuerpo contiene HTML:

1
2
3
4
5
6
7
<?php if ($prioridad === 'alta'): ?>
  <p class="aviso">Prioridad alta: atender cuanto antes.</p>
<?php elseif ($prioridad === 'media'): ?>
  <p>Prioridad media.</p>
<?php else: ?>
  <p>Prioridad baja.</p>
<?php endif ?>

La misma lógica con llaves queda más confusa cuando se mezcla con HTML:

<?php if ($prioridad === 'alta') { ?>
  <p class="aviso">Prioridad alta...</p>
<?php } elseif ($prioridad === 'media') { ?>
  <p>Prioridad media.</p>
<?php } else { ?>
  <p>Prioridad baja.</p>
<?php } ?>

Las dos funcionan; en este proyecto usamos la alternativa con endif siempre que el bloque contenga HTML.

Cada if necesita su endif

Si te saltas un endif, la página entera deja de funcionar: PHP intenta seguir interpretando el resto del fichero como parte del bloque. Cierra siempre los bloques en el orden inverso al que los abriste (primero el más interno, luego el externo).

La expresión match

Cuándo usar match

match (disponible desde PHP 8) es una alternativa compacta a if / elseif / else cuando lo que haces es comparar una variable contra varios valores literales para asignar un resultado.

Sintaxis:

$resultado = match ($variable) {
    valor1         => resultado1,
    valor2         => resultado2,
    valor3, valor4 => resultado_compartido,
    default        => resultado_por_defecto,
};

Cada rama es valor => resultado. Puedes agrupar varios valores con coma. default es la rama que se ejecuta si ninguna otra coincide.

Comparativa if/elseif vs match

Mismo comportamiento, dos estilos:

## Con if/elseif
if ($prioridad === 'alta') {
    $etiqueta_prio = 'URGENTE';
} elseif ($prioridad === 'media') {
    $etiqueta_prio = 'Media';
} elseif ($prioridad === 'baja') {
    $etiqueta_prio = 'Baja';
} else {
    $etiqueta_prio = 'Sin clasificar';
}
1
2
3
4
5
6
7
## Con match
$etiqueta_prio = match ($prioridad) {
    'alta'  => 'URGENTE',
    'media' => 'Media',
    'baja'  => 'Baja',
    default => 'Sin clasificar',
};

Ventajas del match:

  • Más compacto: cada rama en una línea.
  • Comparación estricta automática: match compara con === siempre, sin que lo pidas. En if / elseif tienes que acordarte de escribirlo.

match devuelve un valor, if no

match es una expresión: devuelve un valor que puedes asignar a una variable (como en el ejemplo de arriba). if es una instrucción: no devuelve nada, solo ejecuta bloques de código. Por eso match es ideal para asignaciones y if para ejecutar lógica.

Sin default, match puede lanzar un error

Si el valor no coincide con ninguna rama y no hay default, PHP lanza un error (UnhandledMatchError). Incluye siempre default a menos que estés totalmente seguro de que la variable solo puede tomar los valores listados.

Detalle de sintaxis: la coma al final

Fíjate en que cada rama del match termina en coma, incluida la de default. Es un error habitual olvidarse de alguna y recibir un error de sintaxis:

$x = match ($y) {
    'a' => 1,      ## coma
    'b' => 2,      ## coma
    default => 0,  ## coma (también en la última)
};

El operador ?? (null coalescing)

El operador ?? devuelve el valor de la izquierda si existe y no es null; en otro caso, devuelve el valor de la derecha. Se lee como "coge esto, y si no hay nada, pon esto por defecto".

El uso más típico es leer un parámetro de la URL con un valor por defecto:

$estado = $_GET['estado'] ?? 'abierta';

Qué ocurre según la URL:

URL Valor de $estado
http://gestor.local/estado.php 'abierta' (por defecto, no hay parámetro)
http://gestor.local/estado.php?estado=resuelta 'resuelta'
http://gestor.local/estado.php?estado= '' (cadena vacía, pero la clave existe: ?? no la sustituye)

?? solo actúa cuando el valor es null o la clave no existe. Una cadena vacía '' no la reemplaza. Para tu Lab 04 esto es suficiente; el matiz se profundiza en el apunte de formularios.

Comparación con bash:

Bash PHP
${VAR:-valor_por_defecto} $var ?? 'valor_por_defecto'

El paralelismo es casi exacto: en los dos lenguajes existe un operador corto para "usa esto, o este valor por defecto si no hay nada".

$_GET: qué es y de dónde viene

$_GET es una variable especial de PHP: un array asociativo donde PHP pone automáticamente los parámetros que lleguen por la query string de la URL (todo lo que va después del ?).

Para una URL como http://gestor.local/estado.php?estado=resuelta&prio=alta, PHP crea:

$_GET = [
    'estado' => 'resuelta',
    'prio'   => 'alta',
];

Si no hay query string, $_GET es un array vacío []. Por eso necesitas ?? al leerla: la clave puede no existir.

Filtrar dentro de un foreach

Una técnica muy habitual en listados es combinar foreach con if para mostrar solo los elementos que cumplan una condición. Lo usas para mostrar, por ejemplo, solo las incidencias abiertas de una lista completa:

1
2
3
4
5
6
7
<ul>
<?php foreach ($incidencias as $inc): ?>
  <?php if ($inc['estado'] === 'abierta'): ?>
    <li><?= htmlspecialchars($inc['titulo'], ENT_QUOTES, 'UTF-8') ?></li>
  <?php endif ?>
<?php endforeach ?>
</ul>

Cómo funciona, paso a paso:

  1. El foreach recorre todas las incidencias.
  2. Por cada una, el if decide: si el estado es 'abierta', se pinta el <li>; si no, la iteración no imprime nada y se pasa a la siguiente.
  3. El <ul> final solo contiene las incidencias abiertas, aunque el bucle haya visitado todas.

Cuidado con el orden de cierre

Cuando anidas bloques (un if dentro de un foreach), se cierran en el orden inverso al que se abrieron:

<?php foreach (...): ?>         ## se abre foreach
  <?php if (...): ?>            ## se abre if
    <!-- contenido -->
  <?php endif ?>                ## se cierra if (primero)
<?php endforeach ?>             ## se cierra foreach (después)

Un error común es cerrar primero el endforeach y después el endif. Si lo haces, PHP entiende que estás cerrando bloques que no existen y rompe la página.

Dos variables con el mismo nombre

En el Lab 04 vas a tener dos variables $estado distintas en el mismo fichero, y es importante no confundirlas:

  • $estado del Paso 4 → viene de la URL ($_GET['estado'] ?? 'abierta'). Es el estado "del filtro".
  • $inc['estado'] del Paso 5 → es el estado de cada incidencia dentro del foreach.

La primera la lee PHP antes de empezar el bucle; la segunda cambia en cada iteración. En la ampliación del lab las combinarás (filtrar cada $inc['estado'] comparándolo con el $estado que viene de la URL).