Saltar al contenido
operadores.php · devschool

Operadores en PHP

Lección 5 de 26 · 11 min de lectura · Actualizado el

En esta lección
  1. Operadores aritméticos
  2. Operadores de asignación
  3. Concatenación: el punto
  4. Operadores de comparación
  5. Operadores lógicos
  6. El operador de fusión de null ??
  7. El operador ternario ?:
  8. Incremento y decremento
  9. Errores frecuentes
  10. Resumen

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

OperadorOperaciónEjemploResultado
+Suma7 + 29
-Resta7 - 25
*Multiplicación7 * 214
/División7 / 23.5
%Resto (módulo)7 % 21
**Potencia7 ** 249
$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 /, % o intdiv()) lanza un error DivisionByZeroError que 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:

OperadorEquivale 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:

OperadorSignificado
==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:

  • -1 si el de la izquierda es menor,
  • 0 si son iguales,
  • 1 si 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:

OperadorSignificadoEs true cuando…
&&YLas dos condiciones son verdaderas
||OAl menos una es verdadera
!NOLa condición es falsa
xorO exclusivoExactamente 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 " + $nombre da un TypeError. 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 el 0 y el ""; ?: los trata como falsos.
  • Usar and y or en 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) es 3; 7 / 2 es 3.5.

Resumen

OperadorUso
+ - * / ** %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 : cTernario: 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

[PHP] ¿Qué muestra este código?
$descuento = 0;
echo $descuento ?: 10, " ";
echo $descuento ?? 10;

[PHP] ¿Qué valor tiene $a tras ejecutar la primera línea?
$a = true and false;
var_dump($a);

[PHP] ¿Qué muestra este código?
echo 17 % 5, " ", intdiv(17, 5), " ", 17 / 5;

[PHP] ¿Qué muestra este código con el operador nave espacial?
echo 3 <=> 8, 8 <=> 8, 9 <=> 2;

¿Te ha quedado claro? Márcala y verás tu progreso en el explorador.