En las estructuras if ... elseif ... else ... el orden en que se escriben los casos es importante y, a menudo, se pueden simplificar las condiciones ordenando adecuadamente los casos.
Podemos distinguir dos tipos de situaciones:
Consideremos un programa que genera al azar un valor que corresponde a una edad y en función del valor escribe un mensaje diferente referente al plazo de renovación del carnet de conducir turismos. En España se distinguen tres situaciones (o casos):
Los casos son mutuamente excluyentes, ya que un valor de la edad sólo puede estar en uno de los casos.
<?php
$edad = rand(0, 100);
if ($edad < 18) {
print "<p>Si tiene $edad años, no puede conducir turismos.</p>\n";
} elseif ($edad >= 18 && $edad < 65) {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 10 años.</p>\n";
} else {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 5 años.</p>\n";
}
La siguiente imagen ilustra el orden en que el programa considera los distintos casos:
<?php
$edad = rand(0, 100);
if ($edad < 18) {
print "<p>Si tiene $edad años, no puede conducir turismos.</p>\n";
} elseif ($edad >= 65) {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 5 años.</p>\n";
} else {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 10 años.</p>\n";
}
La siguiente imagen ilustra el orden en que el programa considera los distintos casos:
<?php
$edad = rand(0, 100);
if ($edad < 18) {
print "<p>Si tiene $edad años, no puede conducir turismos.</p>\n";
} elseif ($edad < 65) {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 10 años.</p>\n";
} else {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 5 años.</p>\n";
}
La siguiente imagen ilustra el orden en que el programa considera los distintos casos:
Este programa también funciona correctamente porque en una estructura if ... elseif .. else cuando se cumple una de las comparaciones PHP ya no evalúa las siguientes condiciones. En este caso, si el programa llega a comprobar la segunda comparación (la del elseif), es porque no se ha cumplido la primera (la del if). Y si no se ha cumplido la primera es que $edad es mayor o igual a 18, por lo que no es necesario comprobarlo en la segunda condición.
<?php
// Este programa no funciona correctamente
$edad = rand(0, 100);
if ($edad < 65) {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 10 años.</p>\n";
} elseif ($edad < 18) {
print "<p>Si tiene $edad años, no puede conducir turismos.</p>\n";
} else {
print "<p>Si tiene $edad años, debe renovar el carnet de conducir turismos cada 5 años.</p>\n";
}
La siguiente imagen ilustra el orden en que el programa considera los distintos casos:
Sin embargo, en los dos primeros programas se pueden reordenar los dos primeros casos y los programas siguen funcionando correctamente, ya que en esos programas la segunda condición no se basa en que se hayan filtrado valores en la primera condición.
Consideremos un programa que pide un valor y nos dice:
Nota: El valor 0 se considerará múltiplo de 4 y de 2.
Los casos no son mutuamente excluyentes, puesto que los múltiplos de cuatro son también múltiplos de dos.
<?php
// Este programa no funciona correctamente
$numero = rand(0, 100);
if ($numero % 2 == 0) {
print "<p>$numero es múltiplo de dos.</p>\n";
} elseif ($numero % 4 == 0) {
print "<p>$numero es múltiplo de cuatro y de dos.</p>\n";
} else {
print "<p>$numero no es múltiplo de dos.</p>\n";
}
El error de este programa es que si $numero cumple la segunda condición (la de elseif, ser múltiplo de cuatro), cumple también la primera (la de if, ser múltiplo de dos). Entonces, si $numero es un múltiplo de cuatro, como también es múltiplo de dos, cumple la primera condición y el programa ejecuta el primer bloque de instrucciones, sin llegar a comprobar el resto de condiciones. Así, si por ejemplo $numero es 8, el programa dirá que es múltiplo de dos en vez de decir que es múltiplo de cuatro y de dos.
<?php
$numero = rand(0, 100);
if ($numero % 2 == 0 && $numero % 4 != 0) {
print "<p>$numero es múltiplo de dos.</p>\n";
} elseif ($numero %2 == 0 && $numero % 4 == 0) {
print "<p>$numero es múltiplo de cuatro y de dos.</p>\n";
} else {
print "<p>$numero no es múltiplo de dos.</p>\n";
}
<?php
$numero = rand(0, 100);
if ($numero % 2 == 0 && $numero % 4 != 0) {
print "<p>$numero es múltiplo de dos.</p>\n";
} elseif ($numero % 4 == 0) {
print "<p>$numero es múltiplo de cuatro y de dos.</p>\n";
} else {
print "<p>$numero no es múltiplo de dos.</p>\n";
}
De hecho, aunque sea menos evidente, también bastaría con comprobar en la segunda condición que el número sea múltiplo de dos, puesto que si el programa llega a la segunda condición es que no se ha cumplido la primera, es decir que el número si es múltiplo de dos también es múltiplo de cuatro.
<?php
$numero = rand(0, 100);
if ($numero % 2 == 0 && $numero % 4 != 0) {
print "<p>$numero es múltiplo de dos.</p>\n";
} elseif ($numero % 2 == 0) {
print "<p>$numero es múltiplo de cuatro y de dos.</p>\n";
} else {
print "<p>$numero no es múltiplo de dos.</p>\n";
}
<?php
$numero = rand(0, 100);
if ($numero % 4 == 0) {
print "<p>$numero es múltiplo de cuatro y de dos.</p>\n";
} elseif ($numero % 2 == 0) {
print "<p>$numero es múltiplo de dos.</p>\n";
} else {
print "<p>$numero no es múltiplo de dos.</p>\n";
}
Este programa funciona correctamente ya que aunque la segunda condición (la de elseif) no distingue entre múltiplos de dos y de cuatro, si $numero es un múltiplo de cuatro, el programa no llega a evaluar la segunda condición porque se cumple la primera (la de if).
En general, el orden que permite simplificar más las expresiones suele ser considerar primero los casos particulares y después los casos generales.
En algunos casos, podemos escribir una condición sin necesidad de escribir comparaciones.
Si trabajamos con variables lógicas, no es necesario compararlas con los valores true o false, sino que podemos utilizarlas directamente.
Por ejemplo, el programa siguiente define una variable lógica $esPepe como el resultado de una comparación. Concretamente la variable será true si la variable $nombre es la cadena "Pepe" y false si no.
<?php
$nombre = "Juan";
$esPepe = $nombre == "Pepe";
if ($esPepe == true) {
print "<p>Su nombre es Pepe.</p>\n";
}
if ($esPepe == false) {
print "<p>Su nombre no es Pepe.</p>\n";
}
?>
<p>Su nombre no es Pepe</p>
Pero si hacemos una tabla con los valores de las comparaciones en función de los posibles valores de $esPepe, podemos observar que la comparación de $esPepe con true da el mismo resultado que la propia variable $esPepe, mientras que la comparación con false da resultado contrario:
| $esPepe | $esPepe == true | $esPepe == false |
|---|---|---|
| T | T | F |
| F | F | T |
Por tanto en las condiciones podemos utilizar directamente la variable o su negación en vez de las comparaciones:
<?php
$nombre = "Pepe";
$esPepe = $nombre == "Pepe";
if ($esPepe) {
print "<p>Su nombre es Pepe.</p>\n";
}
if (!$esPepe) {
print "<p>Su nombre no es Pepe.</p>\n";
}
?>
<p>Su nombre es Pepe</p>
Si trabajamos con variables numéricas, no es necesario compararlas con 0, sino que podemos utilizarlas directamente, aprovechando que PHP evalúa el valor 0 (o 0.0) como false y cualquier valor distinto de cero como true.
Nota: Las conversiones implícitas de tipos deben utilizarse con cuidado, cuando estemos seguros de los valores que van a ser convertidos. El uso indiscriminado de conversiones implícitas puede producir errores imprevistos. En caso de duda, es preferible no utilizarlas.
Por ejemplo, el programa siguiente define un contador $cuenta que contiene el número de cincos obtenidos al ejecutar el bucle for.
<?php
$cuenta = 0;
for ($i = 0; $i < 3; $i++) {
$dado = rand(1, 6);
print "<p>Tirada de dado: $dado</p>\n";
if ($dado == 5) {
$cuenta++;
}
}
if ($cuenta == 0) {
print "<p>No ha salido ningún cinco.</p>\n";
}
if ($cuenta > 0) {
print "<p>Han salido $cuenta cinco(s).</p>\n";
}
?>
<p>Tirada de dado: 6</p>
<p>Tirada de dado: 4</p>
<p>Tirada de dado: 1</p>
<p>No ha salido ningún cinco.</p>
Podemos escribir simplemente:
<?php
$cuenta = 0;
for ($i = 0; $i < 3; $i++) {
$dado = rand(1, 6);
print "<p>Tirada de dado: $dado</p>\n";
if ($dado == 5) {
$cuenta++;
}
}
if (!$cuenta) {
print "<p>No ha salido ningún cinco.</p>\n";
}
if ($cuenta) {
print "<p>Han salido $cuenta cinco(s).</p>\n";
}
?>
<p>Tirada de dado: 5</p>
<p>Tirada de dado: 5</p>
<p>Tirada de dado: 1</p>
<p>Han salido 2 cinco(s).</p>
Si trabajamos con cadenas, no es necesario compararlas con la cadena vacía, sino que podemos utilizarlas directamente, aprovechando que PHP evalúa la cadena vacía como false y cualquier valor distinto de la cadena vacía como true.
Nota: Las conversiones implícitas de tipos deben utilizarse con cuidado, cuando estemos seguros de los valores que van a ser convertidos. El uso indiscriminado de conversiones implícitas puede producir errores imprevistos. En caso de duda, es preferible no utilizarlas.
Por ejemplo, el programa siguiente define un contador $cuenta que contiene el número de cincos obtenidos al ejecutar el bucle for.
<?php
$nombre = "";
if ($nombre == "") {
print "<p>No ha escrito su nombre.</p>\n";
}
if ($nombre != "") {
print "<p>Su nombre es $nombre.</p>\n";
}
?>
<p>No ha escrito su nombre.</p>
Podemos escribir simplemente:
<?php
$nombre = "Alberto";
if (!$nombre) {
print "<p>No ha escrito su nombre.</p>\n";
}
if ($nombre) {
print "<p>Su nombre es $nombre.</p>\n";
}
?>
<p>Su nombre es Alberto.</p>
Si las condiciones if ... elseif ... cubren todas las posibilidades, se puede no escribir el bloque else:
<?php
$numero = rand(0, 100);
if ($numero % 2 == 0) {
print "<p>$numero es par.</p>\n";
} elseif ($numero % 2 != 0) {
print "<p>$numero es impar.</p>\n";
}
Pero lo más habitual es sustituir el último bloque elseif ... por un bloque else:
<?php
$numero = rand(0, 100);
if ($numero % 2 == 0) {
print "<p>$numero es par.</p>\n";
} else {
print "<p>$numero es impar.</p>\n";
}