Operadores en PHP
En esta lección
Los operadores son los símbolos que permiten hacer cálculos, comparar valores y combinar condiciones: +, ===, &&… Muchos son iguales que en JavaScript o Java, pero PHP tiene algunos propios, como el punto para unir textos o el operador nave espacial. En esta lección los verás todos, con especial atención a la diferencia entre == y === y a los operadores ?? y ??=, que usarás constantemente con formularios.
Operadores aritméticos
| Operador | Operación | Ejemplo | Resultado |
|---|---|---|---|
+ | Suma | 7 + 2 | 9 |
- | Resta | 7 - 2 | 5 |
* | Multiplicación | 7 * 2 | 14 |
/ | División | 7 / 2 | 3.5 |
% | Resto (módulo) | 7 % 2 | 1 |
** | Potencia | 7 ** 2 | 49 |
$precio = 18;
$personas = 4;
echo $precio * $personas, "\n";
echo 10 / 4, "\n";
echo 9 / 3, "\n";
echo 2 ** 10, "\n";
// 72
// 2.5
// 3
// 1024
La división / devuelve un float cuando el resultado no es exacto y un int cuando lo es.
División entera y resto
Muchas veces no quieres decimales, sino saber cuántas veces cabe un número en otro y cuánto sobra. Para eso están intdiv() y %:
$alumnos = 17;
$porGrupo = 5;
$grupos = intdiv($alumnos, $porGrupo);
$sueltos = $alumnos % $porGrupo;
echo "Grupos completos: $grupos\n";
echo "Alumnos sin grupo: $sueltos\n";
// Grupos completos: 3
// Alumnos sin grupo: 2
El resto % es muy útil para saber si un número es par ($n % 2 === 0), para hacer algo “cada tres filas” o para repartir en turnos. Trabaja con enteros; para el resto con decimales existe la función fmod().
Cuidado: dividir entre cero (con
/,%ointdiv()) lanza un errorDivisionByZeroErrorque detiene el programa. Si el divisor viene del usuario, compruébalo antes.
Orden de las operaciones
Igual que en matemáticas, ** va primero; luego *, / y %; y al final + y -. Los paréntesis cambian el orden:
echo 2 + 3 * 4, "\n";
echo (2 + 3) * 4, "\n";
// 14
// 20
Ante la duda, pon paréntesis. No cuestan nada y hacen el código más claro.
Operadores de asignación
El operador básico es =. Además existen asignaciones combinadas que operan y guardan en un solo paso:
| Operador | Equivale a |
|---|---|
$a += 5 | $a = $a + 5 |
$a -= 5 | $a = $a - 5 |
$a *= 2 | $a = $a * 2 |
$a /= 2 | $a = $a / 2 |
$a %= 3 | $a = $a % 3 |
$a **= 2 | $a = $a ** 2 |
$a .= "x" | $a = $a . "x" |
$saldo = 100;
$saldo -= 30; // pago
$saldo += 15; // devolución
$saldo *= 2; // promoción: saldo doble
echo $saldo, "\n";
// 170
Concatenación: el punto
En PHP los textos se unen con el punto ., no con +. Es una de las diferencias que más cuesta a quien viene de JavaScript:
$nombre = "Sara";
$apellido = "Gómez";
$completo = $nombre . " " . $apellido;
echo $completo . "\n";
$mensaje = "Hola";
$mensaje .= ", " . $nombre;
$mensaje .= ". Tu reserva está confirmada.";
echo $mensaje, "\n";
// Sara Gómez
// Hola, Sara. Tu reserva está confirmada.
.= añade texto al final de una variable. Es muy práctico para construir poco a poco un HTML o un mensaje largo.
¿Por qué PHP usa dos operadores distintos? Precisamente para evitar ambigüedades: + siempre suma y . siempre une. "5" + "5" es 10, y "5" . "5" es "55".
Operadores de comparación
Comparan dos valores y devuelven true o false:
| Operador | Significado |
|---|---|
== | Igual (convierte tipos) |
=== | Idéntico: mismo valor y mismo tipo |
!= o <> | Distinto (convierte tipos) |
!== | No idéntico |
<, > | Menor, mayor |
<=, >= | Menor o igual, mayor o igual |
<=> | Nave espacial: devuelve -1, 0 o 1 |
== frente a ===
== es la igualdad débil: si los tipos no coinciden, PHP intenta convertirlos antes de comparar. === es la igualdad estricta: si los tipos son distintos, ya es false.
var_dump(5 == "5");
var_dump(5 === "5");
var_dump("10" == "10.0");
var_dump(null == false);
var_dump(null === false);
// bool(true)
// bool(false)
// bool(true)
// bool(true)
// bool(false)
"10" y "10.0" son dos textos diferentes, pero == ve que ambos parecen números y los compara como números. Eso puede ser lo que quieres… o un fallo difícil de encontrar.
¿Cuándo usar cada uno?
- Usa
===y!==por defecto. Son predecibles: comparan exactamente lo que ves. - Usa
==solo cuando quieras la conversión a propósito y lo tengas claro.
Un caso real donde === es imprescindible: la función strpos() devuelve la posición donde encuentra un texto (que puede ser 0, el principio) o false si no lo encuentra. Con ==, 0 y false se confundirían.
Comparar textos
Los textos se comparan carácter a carácter, distinguiendo mayúsculas y minúsculas:
var_dump("Madrid" === "madrid");
var_dump("abeja" < "abrigo");
// bool(false)
// bool(true)
Para comparar sin tener en cuenta las mayúsculas, pasa los dos textos a minúsculas antes (lo verás en Cadenas).
La nave espacial <=>
El operador <=> (llamado nave espacial por su forma) compara dos valores y devuelve:
-1si el de la izquierda es menor,0si son iguales,1si el de la izquierda es mayor.
echo 3 <=> 8, "\n";
echo 8 <=> 8, "\n";
echo "pera" <=> "manzana", "\n";
// -1
// 0
// 1
Parece raro, pero es exactamente lo que necesitan las funciones de ordenación como usort(), que verás en Funciones de arrays. Con él, ordenar por precio es una línea.
Operadores lógicos
Combinan condiciones:
| Operador | Significado | Es true cuando… |
|---|---|---|
&& | Y | Las dos condiciones son verdaderas |
|| | O | Al menos una es verdadera |
! | NO | La condición es falsa |
xor | O exclusivo | Exactamente una es verdadera |
$edad = 16;
$autorizacion = true;
$puedeEscalar = $edad >= 18 || $autorizacion;
$esMenor = !($edad >= 18);
var_dump($puedeEscalar, $esMenor);
// bool(true)
// bool(true)
PHP usa evaluación en cortocircuito: en $a && $b, si $a ya es falso, no evalúa $b (el resultado será falso igualmente). En $a || $b, si $a es verdadero, no evalúa $b. Esto permite escribir cosas como $total > 0 && $pagos / $total > 0.5 sin riesgo de dividir entre cero.
&& frente a and
PHP también tiene las palabras and y or. Hacen lo mismo que && y ||, pero con una prioridad mucho más baja, incluso menor que la del =. El resultado sorprende:
$a = true and false;
var_dump($a);
$b = true && false;
var_dump($b);
// bool(true)
// bool(false)
En la primera línea, PHP hace primero $a = true y después evalúa ... and false, cuyo resultado se pierde. Por eso $a vale true. Usa siempre && y ||; si ves or die(...) en código antiguo, es un uso histórico de esta prioridad baja.
El operador de fusión de null ??
?? devuelve el valor de la izquierda si existe y no es null; si no, el de la derecha. Es perfecto para dar valores por defecto:
$datos = ["nombre" => "Pablo"];
$nombre = $datos["nombre"] ?? "Invitado";
$ciudad = $datos["ciudad"] ?? "Sin indicar";
echo "$nombre - $ciudad\n";
// Pablo - Sin indicar
Lo mejor de ?? es que no da aviso aunque la clave o la variable no existan. Sin él, $datos["ciudad"] provocaría un Warning: Undefined array key. Por eso es el compañero inseparable de los formularios: $_GET["pagina"] ?? 1 lee la página si viene en la URL y, si no, usa 1.
Se pueden encadenar: $a ?? $b ?? "por defecto" devuelve el primero que no sea null.
Asignación con ??=
??= asigna un valor solo si la variable no existe o es null:
$opciones = ["idioma" => "es"];
$opciones["idioma"] ??= "en";
$opciones["tema"] ??= "claro";
echo $opciones["idioma"], " / ", $opciones["tema"], "\n";
// es / claro
idioma ya tenía valor y no cambia; tema no existía y recibe "claro".
El operador ternario ?:
El ternario es un if en una sola expresión: condición ? valor_si_true : valor_si_false.
$nota = 6.5;
$resultado = $nota >= 5 ? "Aprobado" : "Suspenso";
echo $resultado, "\n";
// Aprobado
Úsalo para elegir entre dos valores sencillos. Si las ramas tienen varias instrucciones o anidas ternarios, usa un if normal (verás ambos en Condicionales). PHP 8 de hecho prohíbe anidar ternarios sin paréntesis, porque eran muy confusos.
Existe una versión corta, ?: (llamada Elvis), que devuelve el valor de la izquierda si es verdadero y si no el de la derecha:
$apodo = "";
echo $apodo ?: "Anónimo", "\n";
// Anónimo
La diferencia con ?? es importante: ?: mira si el valor es falso ("", 0, "0", null…), mientras que ?? solo mira si es null o no existe.
$descuento = 0;
echo $descuento ?: 10, "\n";
echo $descuento ?? 10, "\n";
// 10
// 0
Si 0 es un valor válido (un descuento del 0 %), ?: lo machaca. En ese caso, ?? es el correcto.
Incremento y decremento
++ suma 1 a una variable y -- le resta 1. Pueden ir delante o detrás, y el matiz importa cuando se usan dentro de otra expresión:
$i++(postincremento): devuelve el valor actual y después suma.++$i(preincremento): suma primero y devuelve el valor nuevo.
$visitas = 5;
echo $visitas++, "\n"; // muestra 5 y luego pasa a 6
echo $visitas, "\n";
echo ++$visitas, "\n"; // pasa a 7 y muestra 7
// 5
// 6
// 7
En la práctica, úsalos en una línea propia ($contador++;) o en los bucles for, y no te tendrás que preocupar por la diferencia.
Errores frecuentes
- Unir textos con
+:"Hola " + $nombreda unTypeError. En PHP se concatena con.. - Usar
=en lugar de===en una condición:if ($rol = "admin")asigna en vez de comparar, y la condición siempre es verdadera. - Comparar con
==y recibir conversiones inesperadas: usa===por defecto. - Confundir
??con?::??respeta el0y el"";?:los trata como falsos. - Usar
andyoren asignaciones: su prioridad es menor que la de=. Usa&&y||. - Dividir sin comprobar el divisor: dividir entre cero detiene el programa con
DivisionByZeroError. - Esperar decimales de
intdiv()o un entero de/:intdiv(7, 2)es3;7 / 2es3.5.
Resumen
| Operador | Uso |
|---|---|
+ - * / ** % | Aritmética; ** potencia, % resto |
intdiv($a, $b) | División entera |
+= -= *= .= | Operar y asignar |
. | Concatenar textos |
=== / !== | Comparar valor y tipo (recomendado) |
== / != | Comparar convirtiendo tipos |
<=> | Devuelve -1, 0 o 1; para ordenar |
&&, ||, ! | Y, O, NO, con cortocircuito |
?? | Valor por defecto si es null o no existe |
??= | Asignar solo si es null o no existe |
a ? b : c | Ternario: elige entre dos valores |
?: | Elvis: valor por defecto si es falso |
++ / -- | Sumar o restar 1 |
En la siguiente lección trabajarás a fondo con textos: cadenas.
Pon a prueba lo que has aprendido
¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.