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.
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.
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.
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
}
?>
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.
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.
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'];
}
?>
(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
?>
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';
}
?>
(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
?>