Operadores de comparación

Los operadores de comparación, como su nombre indica, te permiten comparar dos valores. También puede que te interese ver las tablas de comparación de tipos, ya que muestran ejemplos de varias comparaciones relacionadas con tipos.

Operadores de comparación
Ejemplo Nombre Resultado
$a == $b Igual true si $a es igual a $b después de la conversión de tipos.
$a === $b Identico true si $a es igual a $b, y son del mismo tipo.
$a != $b No igual true si $a no es igual a $b después de la conversión de tipos.
$a <> $b No igual true si $a no es igual a $b después de la conversión de tipos.
$a !== $b No identico true si $a no es igual a $b, o no son del mismo tipo.
$a < $b Menor que true si $a es estricatamente menor que $b.
$a > $b Mayor que true si $a es estrictamente mayor que $b.
$a <= $b Menor o igual a true si $a es menor o igual a $b.
$a >= $b Mayor o igual a true si $a es mayor o igual a $b.
$a <=> $b Operador combinado (operador de nave espacial) Un int menor que, igual a, o mayor que cero cuando $a es menor que, igual a, o mayor que $b, respectivamente.

Si ambos operandos son cadenas numéricas, o uno de los operandos es un número y el otro es una cadena numérica, entonces la comparación se realiza numéricamente. Estos reglas también se aplican a la sentencia switch. El tipo de conversión no se realiza cuando la comparación es === o !== ya que esto implica comparar tanto el tipo como el valor.

Advertencia

Antes de PHP 8.0.0, si una string es comparada con un número o una cadena numérica entonces la string era convertida a un número antes de realizar la comparación. Esto puede llevar a resultados sorprendentes como se puede ver en el siguiente ejemplo:

<?php
var_dump
(0 == "a");
var_dump("1" == "01");
var_dump("10" == "1e1");
var_dump(100 == "1e2");

switch (
"a") {
case
0:
echo
"0";
break;
case
"a":
echo
"a";
break;
}
?>

Salida del ejemplo anterior en PHP 7:

bool(true)
bool(true)
bool(true)
bool(true)
0

Salida del ejemplo anterior en PHP 8:

bool(false)
bool(true)
bool(true)
bool(true)
a

<?php
// Enteros
echo 1 <=> 1; // 0
echo 1 <=> 2; // -1
echo 2 <=> 1; // 1

// Números de punto flotante
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1

// Cadenas
echo "a" <=> "a"; // 0
echo "a" <=> "b"; // -1
echo "b" <=> "a"; // 1

echo "a" <=> "aa"; // -1
echo "zz" <=> "aa"; // 1

// Arrays
echo [] <=> []; // 0
echo [1, 2, 3] <=> [1, 2, 3]; // 0
echo [1, 2, 3] <=> []; // 1
echo [1, 2, 3] <=> [1, 2, 1]; // 1
echo [1, 2, 3] <=> [1, 2, 4]; // -1

// Objetos
$a = (object) ["a" => "b"];
$b = (object) ["a" => "b"];
echo
$a <=> $b; // 0

$a = (object) ["a" => "b"];
$b = (object) ["a" => "c"];
echo
$a <=> $b; // -1

$a = (object) ["a" => "c"];
$b = (object) ["a" => "b"];
echo
$a <=> $b; // 1

// no solo se comparan los valores; las claves deben coincidir
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo
$a <=> $b; // 1

?>

Para varios tipos, la comparación se realiza de acuerdo a la siguiente tabla (en orden).

Comparación con Varios Tipos
Tipo de Operando 1 Tipo de Operando 2 Resultado
null o string string Convertir null a "", comparación numérica o léxica
bool o null cualquier cosa Comvertir ambos operandos a bool, false < true
object object Las clases incorporadas pueden definir su propia comparación, clases diferentes son incomparables, para clases iguales ver Comparación de Objetos
string, recurso, int o float string, recurso, int o float Convertir strings y recursos a números, matemática usual
array array Array con más miembros es mayor, si key de operando 1 no se encuentra en el operando 2 entonces los arrays son incomparables, en caso contrario - comparar valor por valor (ver siguiente ejemplo)
object cualquier cosa El object es siempre mayor
array cualquier cosa El array es siempre mayor

Ejemplo #1 Comparacion Booleano/null

<?php
// Bool y null son comparados siempre como bool
var_dump(1 == TRUE); // TRUE - igual que (bool) 1 == TRUE
var_dump(0 == FALSE); // TRUE - igual que (bool) 0 == FALSE
var_dump(100 < TRUE); // FALSE - igual que (bool) 100 < TRUE
var_dump(-10 < FALSE);// FALSE - igual que (bool) -10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool) NULL < (bool) -100 es FALSE < TRUE
?>

Ejemplo #2 Transcripción de comparación de arrays estándar

<?php
// Arrays con comparadas como esto con operadores de comparación estándar así como el operador de nave espacial.
function standard_array_compare($op1, $op2)
{
if (
count($op1) < count($op2)) {
return -
1; // $op1 < $op2
} elseif (count($op1) > count($op2)) {
return
1; // $op1 > $op2
}
foreach (
$op1 as $key => $val) {
if (!
array_key_exists($key, $op2)) {
return
1;
} elseif (
$val < $op2[$key]) {
return -
1;
} elseif (
$val > $op2[$key]) {
return
1;
}
}
return
0; // $op1 == $op2
}
?>

Advertencia

Comparación de números de punto flotante

Devido a la forma en que los floats son representados internamente, no deberías comparar dos floats para igualdad.

Vease la documentación para float para más información.

Nota: Tenga en cuenta que la conversión de tipos de PHP no siempre es obvia al comparar valores de diferentes tipos, particularmente comparando ints con bools o ints con strings. Por lo tanto, generalmente es recomendable usar comparaciones === y !== en la mayoría de los casos en lugar de == y !=.

Valores Incomparables

Mientras las comparaciones de identidad (=== y !==) pueden ser aplicadas a valores arbitrarios, los otros operadores de comparación solo deberían ser aplicados a valores comparables. El resultado de comparar valores incomparables es indefinido, y no debería depender de ello.

Operador ternario

Otro operador condicional es el operador "?:" (o ternario).

Ejemplo #3 Asignando un valor por defecto

<?php
// Ejemplo de uso: Operador ternario
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// Lo anterior es idéntico a esta sentencia if/else
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
La expresión (expr1) ? (expr2) : (expr3) se evalúa expr2 si expr1 es evaluado como true, y expr3 si expr1 es evaluado como false.

Es posible omitir la parte media del operador ternario. La expresión expr1 ?: expr3 devuelve el resultado de expr1 si expr1 es evaluado como true, y expr3 en caso contrario. expr1 solo es evaluado una vez en este caso.

Nota: Por favor tenga en cuenta que el operador ternario es una expresión, y como tal no es evaluado como una variable, pero sí al resultado de una expresión. Es importante saber esto si se quiere devolver una variable por referencia. La sentencia return $var == 42 ? $a : $b; en una devolución por referencia por lo tanto, no funcionará y se emitirá una advertencia.

Nota:

Es recomendable evitar "apilar" expresiones ternarias. El comportamiento de PHP cuando se usan más de un operador ternario sin paréntesis en una sola expresión no es obvio en comparación con otros lenguajes de programación. De hecho, antes de PHP 8.0.0, las expresiones ternarias se evaluaban de izquierda a derecha, en lugar de derecha a izquierda como la mayoría de los otros lenguajes de programación. Depender de la asociatividad de izquierda está obsoleto a partir de PHP 7.4.0. A partir de PHP 8.0.0, el operador ternario no es asociativo.

Ejemplo #4 Comportamiento no-obvio del operador Ternario

<?php
// En primer momento, lo siguiente parece devolver 'true'
echo (true ? 'true' : false ? 't' : 'f');

// Sin embargo, la salida real de lo anterior es 't' antes de PHP 8.0.0
// esto es porque las expresiones ternarias son asociativas a la izquierda

// La siguiente es una versión más obvia del mismo código que el anterior
echo ((true ? 'true' : false) ? 't' : 'f');

// Aquí, uno puede ver que la primera expresión se evalúa a 'true', que
// a su vez se evalúa a (bool) true, devolviendo así la rama verdadera de la
// segunda expresión ternaria.
?>

Nota:

Encadenando expresiones ternarias cortas (?:), sin embargo, es estable y se comporta razonablemente. Se evaluará al primer argumento que se evalúe como un valor no falso. Tenga en cuenta que los valores indefinidos seguirán generando una advertencia.

Ejemplo #5 Encadenado ternarios cortos

<?php
echo 0 ?: 1 ?: 2 ?: 3, PHP_EOL; //1
echo 0 ?: 0 ?: 2 ?: 3, PHP_EOL; //2
echo 0 ?: 0 ?: 0 ?: 3, PHP_EOL; //3
?>

Operador de Coalescencia de Nulos

Otro operador condicional útil es el operador "??" (o de coalescencia de nulos). Another useful shorthand operator is the "??" (or null coalescing) operator.

Ejemplo #6 Asignando un valor por defecto

<?php
// Ejemplo de uso: Operador de Coalescencia de Nulos
$action = $_POST['action'] ?? 'default';

// Lo anterior es idéntico a esta sentencia if/else
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
La expresión (expr1) ?? (expr2) se evalúa a expr2 si expr1 es null, y expr1 en caso contrario.

En particular, este operador no emite un aviso o advertencia si el valor del lado izquierdo no existe, al igual que isset(). Esto es especialmente útil en claves de arrays.

Nota: Por favor tenga en cuenta que el operador de coalescencia de nulos es una expresión, y como tal no es evaluado como una variable, pero sí al resultado de una expresión. Es importante saber esto si se quiere devolver una variable por referencia. La sentencia return $foo ?? $bar; en una devolución por referencia por lo tanto, no funcionará y se emitirá una advertencia.

Nota:

El operador de coalescencia de nulos tiene una baja precedencia. Esto significa que si se mezcla con otros operadores (como la concatenación de cadenas o los operadores aritméticos) probablemente se requerirán paréntesis.

<?php
// Emitirá una advertencia de que $name es indefinido.
print 'Mr. ' . $name ?? 'Anonymous';

// Imprime "Mr. Anonymous"
print 'Mr. ' . ($name ?? 'Anonymous');
?>

Nota:

Tenga en cuenta que el operador de coalescencia de nulos permite anidamiento simple:

Ejemplo #7 Anidamiento del operador de coalescencia de nulos

<?php

$foo
= null;
$bar = null;
$baz = 1;
$qux = 2;

echo
$foo ?? $bar ?? $baz ?? $qux; // Imprime 1

?>