Saltar a contenido

CONTROL DE FLUJO EN PHP

Estos apuntes son material de consulta para el Lab 04. Cubren los conceptos que se van a aplicar en el mismo: condicionales if / elseif / else, operadores de comparación y lógicos, el operador ?? para leer parámetros de la URL con valor por defecto, el patrón de filtrar con if dentro de un foreach, y la función empty() para detectar listas vacías.

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 (apuntes anteriores), 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).

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://ejemplo.local/pagina.php 'abierta' (por defecto, no hay parámetro)
http://ejemplo.local/pagina.php?estado=resuelta 'resuelta'
http://ejemplo.local/pagina.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 listados básicos esto es suficiente; con formularios conviene una validación más estricta.

$_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://ejemplo.local/pagina.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']) ?></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.

Colisión de nombres entre variable de filtro y campo iterado

A veces un mismo fichero define una variable "global" (por ejemplo, leída de la URL) y dentro de un foreach aparece una clave de array con el mismo nombre. Ejemplo típico: filtrar una lista de elementos por un valor que viene de la URL.

1
2
3
4
5
6
7
$estado = $_GET['estado'] ?? 'todos';   ## valor del filtro (una vez)

foreach ($incidencias as $inc) {
    if ($inc['estado'] === $estado) {   ## ¿cuál es cuál?
        echo $inc['titulo'];
    }
}

Aquí conviven dos cosas distintas que comparten el nombre estado:

Expresión Qué es Cuándo se calcula
$estado El valor del filtro que llega por URL. Una sola vez, antes del bucle.
$inc['estado'] El campo estado del elemento actual del bucle. En cada iteración, con un valor distinto.

PHP las distingue sin problema, pero quien lee el código tiene que recordar cuál es cuál. Para ahorrarte sustos, renombra la variable del filtro para que se vea de un vistazo que no es lo mismo:

1
2
3
4
5
6
7
$filtro_estado = $_GET['estado'] ?? 'todos';

foreach ($incidencias as $inc) {
    if ($inc['estado'] === $filtro_estado) {
        echo $inc['titulo'];
    }
}

Es un poco más largo, pero a cambio el código se lee solo.

Detectar listas vacías con empty()

empty($array) devuelve true si el array está vacío o no existe, y false si tiene al menos un elemento. Es la forma habitual de decidir si mostrar la lista o un mensaje alternativo:

1
2
3
4
5
6
7
8
9
<?php if (empty($incidencias)): ?>
  <p>No hay incidencias registradas.</p>
<?php else: ?>
  <ul>
  <?php foreach ($incidencias as $inc): ?>
    <li><?= htmlspecialchars($inc['titulo']) ?></li>
  <?php endforeach ?>
  </ul>
<?php endif ?>

La estructura tiene dos niveles:

  1. El if (empty(...)) exterior decide entre mensaje o lista.
  2. Si hay datos, el foreach interior los recorre.

Puedes encadenarlo con un filtrado: el if (empty(...)) exterior comprueba si hay incidencias, y dentro del foreach añades otro if que decide qué incidencias muestras (las abiertas, por ejemplo).

empty() no es lo mismo que count($arr) === 0

Las dos hacen lo mismo con un array, pero empty() además devuelve true si la variable no existe o vale null. count() sobre una variable no definida da un aviso. Para decidir "¿hay datos?" en una plantilla HTML, empty() es la opción más segura y compacta.

empty() con cadenas y números

empty() también vale para otros tipos: una cadena '' o '0', el número 0, null y false cuentan como "vacíos". En este lab solo la usarás con arrays, pero es útil saber que no se limita a listas.