PHP 8.3.21 Released!

Operadores de comparación

Los operadores de comparación, como su nombre indica, permiten comparar dos valores. También se debe estar interesado por las tablas de comparaciones de tipos, ya que muestran ejemplos de muchos tipos de comparaciones.

Operadores de comparación
Ejemplo Nombre Resultado
$a == $b Igual true si $a es igual a $b después del transtipado.
$a === $b Idéntico true si $a es igual a $b y son del mismo tipo.
$a != $b Diferente true si $a es diferente de $b después del transtipado.
$a <> $b Diferente true si $a es diferente de $b después del transtipado.
$a !== $b Diferente true si $a es diferente de $b o bien si no son del mismo tipo.
$a < $b Menor que true si $a es estrictamente menor que $b.
$a > $b Mayor true si $a es estrictamente mayor que $b.
$a <= $b Menor o igual true si $a es menor o igual a $b.
$a >= $b Mayor o igual true si $a es mayor o igual a $b.
$a <=> $b Combinado Un int menor, igual o mayor a cero cuando $a es menor, igual, o mayor a $b respectivamente.

Si los dos operandos son strings numéricos, o si un operando es un número y el otro es un string numérico, entonces la comparación se efectuará numéricamente. Estas reglas también se aplican a la instrucción switch. La conversión de tipo no interviene cuando la comparación es === o !== ya que esto implica tanto una comparación de tipo como de valor.

Advertencia

Antes de PHP 8.0.0, si un string es comparado a un número o a un string numérico, entonces el string será convertido en un número antes de efectuar 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

Ejemplo #1 Operadores de comparación

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

// Números flotantes
echo 1.5 <=> 1.5, ' '; // 0
echo 1.5 <=> 2.5, ' '; // -1
echo 2.5 <=> 1.5, ' '; // 1

// Strings
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 las valores son comparados; las claves deben coincidir
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo
$a <=> $b, ' '; // 1

?>

Para los diferentes tipos, la comparación se realiza siguiendo la tabla siguiente (en orden).

Comparación con múltiples tipos
Tipo del operando 1 Tipo del operando 2 Resultado
null o string string Convierte null en "", comparación numérica o léxica
bool o null Cualquier cosa Convierte en bool, false < true
object object Las clases internas pueden definir su propio método de comparación; diferentes clases son incomparables; entre objetos de la misma clase ver Comparación de objetos
string, recurso, int o float string, recurso, int o float Transforma los strings y los recursos en números
array array El array con menos miembros es menor, si la clave del operando 1 no es encontrada en el operando 2, entonces los arrays son incomparables, de lo contrario la comparación se realiza valor por valor (ver el siguiente ejemplo)
object Cualquier cosa El objeto es siempre mayor
array Cualquier cosa El array es siempre mayor

Ejemplo #2 Comparación Booléen/null

<?php
// Booléen y null siempre son comparados como booléans
var_dump(1 == TRUE); // TRUE - idéntico a (bool) 1 == TRUE
var_dump(0 == FALSE); // TRUE - idéntico a (bool) 0 == FALSE
var_dump(100 < TRUE); // FALSE - idéntico a (bool) 100 < TRUE
var_dump(-10 < FALSE);// FALSE - idéntico a (bool) -10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool) NULL < (bool) -100 es idéntico a FALSE < TRUE
?>

Ejemplo #3 Transcripción de las comparaciones estándar de arrays

<?php
// Los arrays son comparados de esta manera con los operadores estándar de comparación y el operador combinado
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

Debido a la forma en que los números de punto flotante son representados internamente, no se debe probar la igualdad entre dos números de tipo float.

Ver la documentación de float para más información.

Nota: Tenga en cuenta que la manipulación de tipos no siempre es evidente al comparar valores de diferentes tipos, en particular al comparar ints con bools o ints con strings. Por lo tanto, generalmente se recomienda utilizar los operadores de comparación === y !== en lugar de == y != en la mayoría de los casos.

Valores incomparables

Mientras que las comparaciones de identidad (=== y !==) pueden ser aplicadas a valores arbitrarios, los otros operadores de comparación solo deben ser aplicados a valores comparables. El resultado de la comparación de valores incomparables es indefinido, y no debe ser utilizado.

El operador ternario

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

Ejemplo #4 Asignación de un valor por defecto

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

// La línea anterior es idéntica a la siguiente condición:
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
La expresión (expr1) ? (expr2) : (expr3) se evalúa a expr2 si expr1 se evalúa a true, y expr3 si expr1 se evalúa a false.

Es posible omitir la parte central del operador ternario. La expresión expr1 ?: expr3 evalúa el resultado de expr1 si expr1 vale true, y expr3 en caso contrario. expr1 solo se evalúa una vez en este caso.

Nota: Tenga en cuenta que el operador ternario es una expresión, y no se evalúa como una variable, sino como el resultado de la expresión. Es importante saberlo si se desea devolver una variable por referencia. La instrucción return $var == 42 ? $a : $b; en una función devuelta por referencia no funcionará y se emitirá una alerta.

Nota:

Se recomienda no "apilar" las expresiones ternarias. El comportamiento de PHP al utilizar varios operadores ternarios que no están entre paréntesis en una única expresión es no evidente en comparación con otros lenguajes. Anteriormente a PHP 8.0.0, el operador ternario se evaluaba de izquierda a derecha, en lugar de derecha a izquierda como la mayoría de los otros lenguajes de programación. Dependiendo de la asociatividad a la izquierda es obsoleto a partir de PHP 7.4.0. A partir de PHP 8.0.0, el operador ternario no es asociativo.

Ejemplo #5 Comportamiento de PHP

<?php
// A primera vista, lo siguiente debería devolver 'true'
echo (true ? 'true' : false ? 't' : 'f');

// sin embargo, la expresión anterior devolverá 't' antes de PHP 8.0.0
// porque el operador ternario es de izquierda a derecha

// la siguiente expresión es una versión más evidente del mismo código
echo ((true ? 'true' : false) ? 't' : 'f');

// aquí, se puede observar que la primera expresión se evalúa a 'true',
// lo que hace que se evalúe a (bool)true, lo que devuelve la rama
// 'verdadera' de la segunda expresión ternaria.
?>

Nota:

La combinación de ternario corto (?:), sin embargo, es estable y se comporta de manera razonable. Esto evaluará el primer argumento que evalúa a un valor no-falsy. Tenga en cuenta que los valores indefinidos siempre emitirán un aviso.

Ejemplo #6 Combinación de ternario corto

<?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 fusión Null

Otro operador corto útil es el operador "??" (o fusión null).

Ejemplo #7 Asignar un valor por defecto

<?php
// Ejemplo de uso para: Operador de fusión Null
$action = $_POST['action'] ?? 'default';

// el código anterior es equivalente a la siguiente estructura if/else
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
La expresión (expr1) ?? (expr2) devuelve expr2 si expr1 es null, y expr1 en los otros casos.

En particular, este operador no emite una notificación o advertencia si la parte izquierda no existe, exactamente como isset(). Esto es especialmente útil para las claves de los arrays.

Nota: Tenga en cuenta que el operador de fusión null es una expresión, y que no se evalúa como una variable, sino como el resultado de una expresión. Es importante saberlo si se desea devolver una variable por referencia. La expresión return $foo ?? $bar; es un retorno por referencia que no funciona y emite una advertencia.

Nota:

El operador de fusión null tiene una precedencia baja. Esto significa que al mezclarlo con otros operadores (como la concatenación de strings o los operadores aritméticos) se requerirán paréntesis.

<?php
// Emite una advertencia de que $name es indefinida.
print 'Mr. ' . $name ?? 'Anonymous';

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

Nota:

Tenga en cuenta que el operador de fusión null permite una imbricación simple:

Ejemplo #8 Imbricación de la operación de fusión null

<?php

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

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

?>

add a note

User Contributed Notes 14 notes

up
170
crazy888s at hotmail dot com
15 years ago
I couldn't find much info on stacking the new ternary operator, so I ran some tests:

<?php
echo 0 ?: 1 ?: 2 ?: 3; //1
echo 1 ?: 0 ?: 3 ?: 2; //1
echo 2 ?: 1 ?: 0 ?: 3; //2
echo 3 ?: 2 ?: 1 ?: 0; //3

echo 0 ?: 1 ?: 2 ?: 3; //1
echo 0 ?: 0 ?: 2 ?: 3; //2
echo 0 ?: 0 ?: 0 ?: 3; //3
?>

It works just as expected, returning the first non-false value within a group of expressions.
up
5
gfilippakis at sleed dot gr
2 years ago
Please note that using the null coalescing operator to check properties on a class that has the __get magic method (without an __isset magic method) invokes the magic method.

For example:

<?php

class A
{
public function
__get($property)
{
echo
'Called __get for ' . $property . PHP_EOL;
}
}

$a = new A();

echo
'Trying null coalescing operator' . PHP_EOL;
$b = $a->test ?? 5;

echo
'Trying isset()' . PHP_EOL;
if (isset(
$a->test)) {
$b = $a->test;
} else {
$b = 5;
}

?>
up
21
adam at caucho dot com
19 years ago
Note: according to the spec, PHP's comparison operators are not transitive. For example, the following are all true in PHP5:

"11" < "a" < 2 < "11"

As a result, the outcome of sorting an array depends on the order the elements appear in the pre-sort array. The following code will dump out two arrays with *different* orderings:

<?php
$a
= array(2, "a", "11", 2);
$b = array(2, "11", "a", 2);
sort($a);
var_dump($a);
sort($b);
var_dump($b);
?>

This is not a bug report -- given the spec on this documentation page, what PHP does is "correct". But that may not be what was intended...
up
9
Tahazzot
4 years ago
Very careful when reading PHP documentation, Here's a lot of miss information.

According to documentation, They say's (int) 0 == (string) "a" is true. But it is not in PHP 8.

var_dump(0 == "a"); // 0 == 0 -> true

Now In PHP 8 it's False.
up
5
Sumon Mahmud
5 years ago
Extending from here: https://www.php.net/manual/en/language.operators.comparison.php#121907

$a = ['a' => 1, 'b' => 2, 'c' => 3, 'e' => 4];
$b = ['a' => 1, 'b' => 2, 'd' => 3, 'e' => 4];

echo $a > $b; // 0
echo $b > $a; // 0
echo $a <$b; // 0
echo $b < $a; // 0

If using spaceship operator then it is returning true like :

echo $a <=> $b; //1
echo $b <=> $a; //1
echo $a <=> $b; //1
echo $b <=> $a; //1
up
16
rshawiii at yahoo dot com
19 years ago
You can't just compare two arrays with the === operator
like you would think to find out if they are equal or not. This is more complicated when you have multi-dimensional arrays. Here is a recursive comparison function.

<?php
/**
* Compares two arrays to see if they contain the same values. Returns TRUE or FALSE.
* usefull for determining if a record or block of data was modified (perhaps by user input)
* prior to setting a "date_last_updated" or skipping updating the db in the case of no change.
*
* @param array $a1
* @param array $a2
* @return boolean
*/
function array_compare_recursive($a1, $a2)
{
if (!(
is_array($a1) and (is_array($a2)))) { return FALSE;}

if (!
count($a1) == count($a2))
{
return
FALSE; // arrays don't have same number of entries
}

foreach (
$a1 as $key => $val)
{
if (!
array_key_exists($key, $a2))
{return
FALSE; // uncomparable array keys don't match
}
elseif (
is_array($val) and is_array($a2[$key])) // if both entries are arrays then compare recursive
{if (!array_compare_recursive($val,$a2[$key])) return FALSE;
}
elseif (!(
$val === $a2[$key])) // compare entries must be of same type.
{return FALSE;
}
}
return
TRUE; // $a1 === $a2
}
?>
up
13
bishop
18 years ago
When you want to know if two arrays contain the same values, regardless of the values' order, you cannot use "==" or "===". In other words:

<?php
(array(1,2) == array(2,1)) === false;
?>

To answer that question, use:

<?php
function array_equal($a, $b) {
return (
is_array($a) && is_array($b) && array_diff($a, $b) === array_diff($b, $a));
}
?>

A related, but more strict problem, is if you need to ensure that two arrays contain the same key=>value pairs, regardless of the order of the pairs. In that case, use:

<?php
function array_identical($a, $b) {
return (
is_array($a) && is_array($b) && array_diff_assoc($a, $b) === array_diff_assoc($b, $a));
}
?>

Example:
<?php
$a
= array (2, 1);
$b = array (1, 2);
// true === array_equal($a, $b);
// false === array_identical($a, $b);

$a = array ('a' => 2, 'b' => 1);
$b = array ('b' => 1, 'a' => 2);
// true === array_identical($a, $b)
// true === array_equal($a, $b)
?>

(See also the solution "rshawiii at yahoo dot com" posted)
up
6
admin at zeros dot co dot id
2 years ago
Please be careful when you try to compare strings that have a plus sign `+` at the beginning (such as phone number, etc). When you use the Equal operator `==` PHP will ignore the plus sign. Use Identical operator `===` instead

Example:

$str1 = "62";
$str2 = "+62";

var_dump($str1 == $str2); // bool(true)
var_dump($str1 === $str2); // bool(false)
up
4
niall at maranelda dot org
7 years ago
Care must be taken when using the spaceship operator with arrays that do not have the same keys:

- Contrary to the notes above ("Example #2 Transcription of standard array comparison"), it does *not* return null if the left-hand array contains a key that the right-hand array does not.
- Because of this, the result depends on the order you do the comparison in.

For example:

<?php
$a
= ['a' => 1, 'b' => 2, 'c' => 3, 'e' => 4];
$b = ['a' => 1, 'b' => 2, 'd' => 3, 'e' => 4];

var_dump($a <=> $b); // int(1) : $a > $b because $a has the 'c' key and $b doesn't.

var_dump($b <=> $a); // int(1) : $b > $a because $b has the 'd' key and $a doesn't.
?>
up
4
Ryan Mott
5 years ago
Searching for "double question mark" operator should find this page (and hopefully after this comment the crawlers will agree)
up
1
Hayley Watson
1 year ago
Between the "shortcut ternary" (aka "elvis") and "spaceship" operators, you can write some quite compact comparison functions for usort and its ilk.

If you want to sort an array of associative arrays by several different keys you can chain them in the same way that you can list column names in an SQL ORDER BY clause.

<?php
usort
($array, fn($a, $b) => $a['a'] <=> $b['a']
?:
$b['b'] <=> $a['b']
?:
$a['c'] <=> $b['c']);
?>
Will sort the array by column 'a', then by column 'b' descending, then by column 'c'; or in SQL-speak 'ORDER BY a, b DESC, c".
up
6
Cuong Huy To
13 years ago
In the table "Comparison with Various Types", please move the last line about "Object" to be above the line about "Array", since Object is considered to be greater than Array (tested on 5.3.3)

(Please remove my "Anonymous" post of the same content before. You could check IP to see that I forgot to type my name)
up
1
Marcin Kuzawiski
9 years ago
A < B and still B < A...

$A = [1 => 1, 2 => 0, 3 => 1];
$B = [1 => 1, 3 => 0, 2 => 1];

var_dump($A < $B); // TRUE
var_dump($B < $A); // TRUE

var_dump($A > $B); // TRUE
var_dump($B > $A); // TRUE

Next - C and D are comparable, but neither C < D nor D < C (and still C != D)...

$C = [1 => 1, 2 => 1, 3 => 0];
$D = [1 => 1, 3 => 1, 2 => 0];

var_dump($C < $D); // FALSE
var_dump($D < $C); // FALSE

var_dump($C > $D); // FALSE
var_dump($D > $C); // FALSE

var_dump($D == $C); // FALSE
up
-1
billynoah at gmail dot com
3 months ago
It's worth noting that there can be a difference in the logical operation of shorthand ternary (expr1 ?: expr2) vs the full version (expr1 ? expr1 : expr2). The shorthand style may also offer a slight performance enhancement because the initial expression will only be evaluated once.

Example:
<?php
// my_func() will be called twice here
// additionally, my_func() may not return the same value both times!
$var = my_func() ? my_func() : false;

// my_func() will only be called once here
$var = my_func() ?: false;
To Top