PHP 8.4.1 Released!

Operatori di confronto

Gli operatori di confronto, come suggerisce il loro nome, permettono di confrontare due valori. Può essere interessante vedere la tabella di raffronto dei tipi, dato che mostra esempi di vari confronti tra i tipi di variabili.

Operatori di confronto
Esempio Nome Risultato
$a == $b Uguale true se $a è uguale a $b dopo la manipolazione dei tipi.
$a === $b Identico true se $a è uguale a $b, ed sono dello stesso tipo.
$a != $b Diversi true se $a è diverso da $b dopo la manipolazione dei tipi.
$a <> $b Diversi true se $a è diverso da $b dopo la manipolazione dei tipi.
$a !== $b Non identici true se $a è diverso da $b, o se non sono dello stesso tipo.
$a < $b Minore true se $a è strettamente minore di $b.
$a > $b Maggiore true se $a è strettamente maggiore di $b.
$a <= $b Minore o uguale true se $a è minore o uguale a $b.
$a >= $b Maggiore o uguale true se $a è maggiore o uguale a $b.
$a <=> $b Spaceship Un int minore di, uguale a, o maggiore di zero quando $a è minore di, uguale a, o maggiore di $b.

Se entrambi gli operandi sono stringhe numeriche o un operando è un numero e l'altro è una stringa numerica, quindi il confronto viene eseguito numericamente. Queste regole si applicano anche all' istruzione switch. La conversione del tipo non ha luogo quando il confronto è === o !== poiché implica il confronto del tipo e del valore.

Avviso

Prima di PHP 8.0.0, se una stringa veniva confrontata con un numero o una stringa numerica, la stringa veniva convertita in un numero prima di eseguire il confronto. Questo può portare a risultati sorprendenti, come si può vedere con il seguente esempio:

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

Output of the above example in PHP 7:

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

Output of the above example in PHP 8:

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

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

// Numeri float
echo 1.5 <=> 1.5; // 0
echo 1.5 <=> 2.5; // -1
echo 2.5 <=> 1.5; // 1

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

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

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

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

// non vengono confrontati solo i valori; le chiavi devono corrispondere
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo
$a <=> $b; // 1

?>

Se i tipi di operandi utilizzati differiscono, il confronto viene svolto nell'ordine indicato della seguente tabella.

Confronti con differenti tipi
Tipo dell'operando 1 Tipo dell'operando 2 Risultato
null oppure string string Si converte null in "", confronto numerico o lessicale
bool oppure null qualsiasi Converte entrambi i lati in bool, false < true
object object Le classi predefinite possono avere la propria funzione di confronto, classi differenti non sono confrontabili, per la stessa classe vedere Confronto di Oggetti.
string, resource, int oppure float string, resource, int oppure float Stringhe e risorse sono converti in numeri, confronto matematico
array array La matrice con meno membri è più piccola, se la chiave dell'operando 1 non si trova nell'operando 2 allora le matrici non si possono confrontare, in altri casi il confronto avviene valore per valore (vedere l'esempio seguente)
object qualsiasi object è sempre più grande
array qualsiasi array è sempre più grande

Example #1 Confronto Boolean/null

<?php
// Bool e null sono confrontati sempre come bool
var_dump(1 == TRUE); // TRUE - uguale a (bool)1 == TRUE
var_dump(0 == FALSE); // TRUE - uguale a (bool)0 == FALSE
var_dump(100 < TRUE); // FALSE - uguale a (bool)100 < TRUE
var_dump(-10 < FALSE);// FALSE - uguale a (bool)-10 < FALSE
var_dump(min(-100, -10, NULL, 10, 100)); // NULL - (bool)NULL < (bool)-100 è FALSE < TRUE
?>

Example #2 Trascrizione del confronto standard tra matrici

<?php
// Gli array vengono confrontati in questo modo con gli operatori di confronto standard e con l'operatore 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
}
?>

Avviso

Confronto di numeri in virgola mobile

A causa del modo in cui i float sono rappresentati internamente al PHP, non si dovrebbe esaminare l'eguaglianza di due float.

Per maggior informazioni, fare riferimento alla documentazione del tipo float.

Nota: Tenere presente che la manipolazione dei tipi di PHP non è sempre ovvia quando si confrontano valori di tipi diversi, in particolare confrontando int con bool o int con string. È quindi generalmente consigliabile utilizzare confronti === e !== piuttosto che == e != nella maggior parte dei casi.

Incomparable Values

Mentre il confronto di identità (=== e !==) può essere applicato a valori arbitrari, gli altri operatori di confronto dovrebbero essere applicati solo a valori comparabili. Il risultato del confronto di valori incomparabili non è definito e non dovrebbe essere considerato attendibile.

Operatore ternario

Un altro operatore condizionale è l'operatore ternario "?:".

Example #3 Assegnazione di un valore di default

<?php
// Esempio di utilizzo dell'operatore ternario
$action = (empty($_POST['action'])) ? 'default' : $_POST['action'];

// La riga precedente è simile a
if (empty($_POST['action'])) {
$action = 'default';
} else {
$action = $_POST['action'];
}
?>
L'espressione (espressione1) ? (espressione2) : (espressione3) vale espressione2 se espressione1 è true, e espressione3 se espressione1 è false.

È possibile tralasciare l'elemento centrale dell'operatore ternario. L'espressione espressione1 ?: espressione3 viene valutata al risultato di espressione1 se espressione1 viene valutata true, e espressione3 in caso contrario. espressione1 viene valutata solo una volta.

Nota: Si noti che l'operatore ternario è un'espressione, e non viene valutato come variabile, ma come risultato di un'espressione. Questo è importante da sapere nel caso si desideri restituire una variabile per riferimento. La riga return $var == 42 ? $a : $b; in una funzione che restituisce per riferimento non funzionerà e genererà un avvertimento.

Nota:

Si raccomanda di evitare di "sovrapporre" espressioni ternarie. Il comportamento di PHP quando si utilizza più di un operatore ternario senza parentesi all'interno di una singola espressione non è ovvio rispetto ad altri linguaggi. In effetti, prima di PHP 8.0.0, le espressioni ternarie venivano valutate associative a sinistra, anziché associative a destra come la maggior parte degli altri linguaggi di programmazione. Fare affidamento sull'associatività di sinistra è deprecato a partire da PHP 7.4.0. A partire da PHP 8.0.0, l'operatore ternario non è associativo.

Example #4 Comportamento ternario non ovvio

<?php
// a prima vista, questa istruzione dovrebbe restituire 'true'
echo (true ? 'true' : false ? 't' : 'f');

// invece, l'output effettivo di quanto sopra è 't' prima di PHP 8.0.0
// questo perché le espressioni ternarie sono associative a sinistra

// quanti segue è una versione più chiara dello stesso codice
echo ((true ? 'true' : false) ? 't' : 'f');

// qui, si può notare che la prima espressione viene valutata come "true", che
// a sua volta diventa (bool)true, e quindi restituisce il ramo true della
// seconda espressione ternaria.
?>

Nota:

Il concatenamento di ternari brevi (?:), tuttavia, è stabile e si comporta in modo ragionevole. Verrà valutato al primo argomento valutato come valore non falso. Si noti che i valori non definiti genereranno comunque un avviso.

Example #5 Concatenamento ternario breve

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

L'operatore Null Coalescing

Un altro utile operatore abbreviato è il "??" (o null coalescing).

Example #6 Assegnazione di un valore predefinito

<?php
// Esempio di utilizzo per: Operatore Null Coalesce
$action = $_POST['action'] ?? 'default';

// Quello sopra è identico a questa istruzione if/else
if (isset($_POST['action'])) {
$action = $_POST['action'];
} else {
$action = 'default';
}
?>
L'espressione (expr1) ?? (expr2) viene valutata a expr2 se expr1 è null, e expr1 in caso contrario.

In particolare, questo operatore non emette un avviso o un avvertimento se il valore del lato sinistro non esiste, proprio come isset(). Questo è particolarmente utile sulle chiavi degli array.

Nota: Si prega di notare che l'operatore null coalescing è un'espressione, e che essa non viene valutata ad una variabile, ma al risultato di un'espressione. Questo è importante da sapere nel caso in cui si volesse restituire una variabile per riferimento. L'istruzione return $foo ?? $bar; in una funzione che restituisce un riferimento quindi non funzionerà e verrà emesso un avviso.

Nota:

L'operatore null coalescing ha una precedenza bassa. Ciò significa che se lo si mescola con altri operatori (come la concatenazione di stringhe o gli operatori aritmetici) saranno probabilmente necessarie parentesi.

<?php
// Genera un avviso che $name non è definito.
print 'Mr. ' . $name ?? 'Anonymous';

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

Nota:

Si prega di notare che l'operatore null coalescing permette semplici nidificazioni:

Example #7 Operatore null coalescing nidificato

<?php

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

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

?>

add a note

User Contributed Notes 13 notes

up
173
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
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
3
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
23
adam at caucho dot com
18 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
3 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
8
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
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
3
gfilippakis at sleed dot gr
1 year 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
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
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
3
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
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
2
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
To Top