PHP 8.3.4 Released!

Operadores de Comparação

Operadores de comparação, como os seus nomes implicam, permitem que você compare dois valores. Você pode se interessar em ver as tabelas de comparação de tipos, que tem exemplo das várias comparações entre tipos relacionadas.

Operadores de comparação
Exemplo Nome Resultado
$a == $b Igual true se $a é igual a $b após equalização de tipos.
$a === $b Idêntico true se $a é igual a $b, e eles são do mesmo tipo.
$a != $b Diferente true se $a não é igual a $b depois de equalização de ativos.
$a <> $b Diferente true se $a não é igual a $b depois de equalização de ativos.
$a !== $b Não idêntico true se $a não é igual a $b, ou eles não são do mesmo tipo.
$a < $b Menor que true se $a é estritamente menor que $b.
$a > $b Maior que true se $a é estritamente maior que $b.
$a <= $b Menor ou igual true se $a é menor ou igual a $b.
$a >= $b Maior ou igual true se $a é maior ou igual a $b.
$a <=> $b Spaceship (nave espacial) Um int menor que, igual a ou maior que zero quando $a é, respectivamente, menor que, igual a ou maior que $b.

Se ambos os operadores são strings numéricas, ou um operando é um número e o outro é uma string numérica, então a comparação é realizada numericamente. Estas regras se aplicam à instrução switch. A conversão de tipos não é realizada quando a comparação é realizada através === ou !== porque aqui é realizada a comparação de tipos, além de valores.

Aviso

Anteriormente ao PHP 8.0.0, se uma string era comparada a um número ou uma string numérica, então a string era convertida para número antes de realizar a comparação. Isto pode levar a resultados inesperados, como observado no exemplo a seguir:

<?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;
}
?>

Saída do exemplo acima no PHP 7:

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

Saída do exemplo acima no PHP 8:

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

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

// Floats
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

// Objects
$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

// valores e tipos precisam coincidir
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo
$a <=> $b; // 1

?>

Para vários tipos, comparações são feitas de acordo com a seguinte tabela (em ordem).

Comparação com vários tipos
Tipo do 1º operando Tipo do 2º operando Resultado
null ou string string Converte null para "", numérico ou comparação léxica
bool or null qualquer Converte para bool, false < true
object object Classes nativas podem definir suas próprias comparações, classes diferentes são incomparáveis, same class see Comparação de Objetos
string, resource, int ou float string, resource, int ou float Transforma strings e resources para números
array array Array com menos membros é menor, se a chave do operando 1 não é encontrada no operando 2, então os arrays são incomparáveis, caso contrário compara valor por valor (veja o seguinte exemplo)
object qualquer object é sempre maior
array qualquer array é sempre maior

Exemplo #1 Comparações de boolean e null

<?php
// Bool e null são sempre comparados como booleanos
var_dump(1 == TRUE); // TRUE - same as (bool)1 == TRUE
var_dump(0 == FALSE); // TRUE - same as (bool)0 == FALSE
var_dump(100 < TRUE); // FALSE - same as (bool)100 < TRUE
var_dump(-10 < FALSE);// FALSE - same as (bool)-10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool)NULL < (bool)-100 is FALSE < TRUE
?>

Exemplo #2 Transcrição do padrão de comparação de array

<?php
// Arrays são comparados assim quando utilizando-se os operadores padrão e operador spaceship
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
}
?>

Aviso

Comparison of floating point numbers

Por conta da forma que floats são representados internamente não se deve testar dois floats com o comparador de igualdade.

Veja a documentação de float para mais detalhes.

Nota: Cuidado. A conversão automática de tipos do PHP não é sempre tão óbiva, quando comparando valores de tipos diferentes, particularmente comparando ints para bools ou ints para strings. No geral é recomendado utilizar as comparações === e !== em vez de utilizar == e != na maioria dos casos.

Valores não comparáveis

Embora a comparação de identidade (=== e !==) possa ser aplicada para valores arbitrários, os outros operadores de comparação somente devem ser aplicados a valores comparáveis. O resultado de comparação de valores não comparáveis não é definida, e não pode ser garantida.

Operador Ternário

Outro operador condicional é o operador "?:" (ou ternário).

Exemplo #3 Atribuindo um valor padrão

<?php
// Example usage for: Ternary Operator
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// The above is identical to this if/else statement
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
A expressão (expr1) ? (expr2) : (expr3) é avaliada para expr2 se expr1 é avaliada como true, ou expr3 se expr1 é avaliada como false.

É possível deixar vazia a parte central do operador ternário. A expressão expr1 ?: expr3 retorna o resultado de expr1 se expr1 avaliar para true, e expr3 se não. expr1 somente é avaliada nessa única situação.

Nota: Note que o operador ternário é uma expressão, e ele não é avaliado para uma variável, mas para o resultado de uma expressão. Isto é importante saber se você quer retornar uma variável por referência. A declaração return $var == 42 ? $a : $b; em uma função que retorna por referência conseqüêntemente não irá funcionar e será avisado.

Nota:

É recomendado evitar empilhar operadores ternários. O comportamento do PHP quando utilizando mais de um operador ternário sem parênteses numa única expressão é menos óbvia, comparada a outras linguagesn. Antes do PHP 8.0.0, os operadores ternários eram avaliados com associatividade à esquerda, em vez de associatividade à direta, como na maioria de outras linguagens. Depender da associatividade à esquerda foi descontinuado a partir do PHP 7.4.0. A partir do PHP 8.0.0, o operador ternário é não associativo.

Exemplo #4 Comportamento não óbvio do ternário

<?php
// Pode parecer que a expressão a seguir imprime 'true'
echo (true ? 'true' : false ? 't' : 'f');

// No entanto, a saída é na verdade 't' antes do PHP 8.0.0
// Isto ocorre porque operadores ternários são associativos à esquerda

// O seguinte é a versão mais intuitiva do código acima
echo ((true ? 'true' : false) ? 't' : 'f');

// Aqui, é possível ver que a primeira expressão avalia para 'true', e então
// é avalidada para (bool)true, e portanto retorna o variante true da
// segunda expressão ternária
?>

Nota:

Encadeamento de ternários curtos (?:), é estável, e comporta-se intuitivamente. Ele avaliará como o primeiro argumento que avalia para uma valor não falso. Observe que valores não definidos irão emitir um alerta.

Exemplo #5 Encadeamento de ternários curtos

<?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 aglunitação null (Null Coalescing)

Existe ainda o operador "??" (ou null coalescing).

Exemplo #6 Atribuindo um valor padrão

<?php
// Exemplo do operador Null Coalesce
$action = $_POST['action'] ?? 'default';

// O conteúdo acima é idêntico à essa declaração if/else
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
A expressão (expr1) ?? (expr2) é avaliada para expr2 se expr1 for null, e expr1 do contrário.

Esse operador em particular não emite aviso caso o valor da esquerda não exista, assim como isset(). Sendo especialmente útil em chaves de arrays.

Nota: Note que o operador null coalescing é uma expressão, e ele não é avaliado para uma variável, mas para o resultado de uma expressão. Isto é importante saber se você quer retornar uma variável por referência. A declaração return $foo ?? $bar; em uma função que retorna por referência conseqüêntemente não irá funcionar e será avisado.

Nota:

O operador de aglutinação null tem baixa precedência. Isso significa que misturá-lo com outros operadores (como por exemplo concatenação ou aritmética) irá provavelmente exigir parênteses.

<?php
// Emite um aviso que $name não está definido.
print 'Mr. ' . $name ?? 'Anonymous';

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

Nota:

Note que o operador null coalescing permite a criação de aninhamentos simples:

Exemplo #7 Aninhando o operador null coalescing

<?php

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

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

?>

add a note

User Contributed Notes 13 notes

up
174
crazy888s at hotmail dot com
14 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
8
admin at zeros dot co dot id
1 year 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
5
Sumon Mahmud
4 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
24
adam at caucho dot com
17 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
8
Tahazzot
2 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
18
rshawiii at yahoo dot com
18 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
17 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
2
gfilippakis at sleed dot gr
11 months 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
1
Hayley Watson
7 months 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
5
Marcin Kuzawiski
8 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
4
niall at maranelda dot org
6 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
2
Ryan Mott
4 years ago
Searching for "double question mark" operator should find this page (and hopefully after this comment the crawlers will agree)
up
5
Cuong Huy To
12 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)
To Top