比較運(yùn)算符

比較運(yùn)算符,如同它們名稱(chēng)所暗示的,允許對(duì)兩個(gè)值進(jìn)行比較。還可以參考 PHP 類(lèi)型比較表看不同類(lèi)型相互比較的例子。

比較運(yùn)算符
例子 名稱(chēng) 結(jié)果
$a == $b 等于 true,如果類(lèi)型轉(zhuǎn)換后 $a 等于 $b。
$a === $b 全等 true,如果 $a 等于 $b,并且它們的類(lèi)型也相同。
$a != $b 不等 true,如果類(lèi)型轉(zhuǎn)換后 $a 不等于 $b
$a <> $b 不等 true,如果類(lèi)型轉(zhuǎn)換后 $a 不等于 $b
$a !== $b 不全等 true,如果 $a 不等于 $b,或者它們的類(lèi)型不同。
$a < $b 小與 true,如果 $a 嚴(yán)格小于 $b。
$a > $b 大于 true,如果 $a 嚴(yán)格大于 $b。
$a <= $b 小于等于 true,如果 $a 小于或者等于 $b。
$a >= $b 大于等于 true,如果 $a 大于或者等于 $b。
$a <=> $b 太空船運(yùn)算符(組合比較符) 當(dāng)$a小于、等于、大于 $b時(shí) 分別返回一個(gè)小于、等于、大于0的 int 值。

當(dāng)兩個(gè)操作對(duì)象都是 數(shù)字字符串, 或一個(gè)是數(shù)字另一個(gè)是 數(shù)字字符串, 就會(huì)自動(dòng)按照數(shù)值進(jìn)行比較。 此規(guī)則也適用于 switch 語(yǔ)句。 當(dāng)比較時(shí)用的是 ===!==, 則不會(huì)進(jìn)行類(lèi)型轉(zhuǎn)換——因?yàn)椴粌H要對(duì)比數(shù)值,還要對(duì)比類(lèi)型。

警告

PHP 8.0.0 之前,如果 string 與數(shù)字或者數(shù)字字符串進(jìn)行比較, 則在比較前會(huì)將 string 轉(zhuǎn)化為數(shù)字。 在如下示例中會(huì)出現(xiàn)不可預(yù)料的結(jié)果:

<?php
var_dump
(== "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;
}
?>

以上例程在 PHP 7 中的輸出:

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

以上例程在 PHP 8 中的輸出:

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

<?php
// 整數(shù)
echo <=> 1// 0
echo <=> 2// -1
echo <=> 1// 1

// 浮點(diǎn)數(shù)
echo 1.5 <=> 1.5// 0
echo 1.5 <=> 2.5// -1
echo 2.5 <=> 1.5// 1

// 字符串
echo "a" <=> "a"// 0
echo "a" <=> "b"// -1
echo "b" <=> "a"// 1

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

// 數(shù)組
echo [] <=> []; // 0
echo [123] <=> [123]; // 0
echo [123] <=> []; // 1
echo [123] <=> [121]; // 1
echo [123] <=> [124]; // -1

// 對(duì)象
$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

// 不僅僅比較值,而且也會(huì)匹配鍵
$a = (object) ["a" => "b"];
$b = (object) ["b" => "b"];
echo 
$a <=> $b// 1

?>

對(duì)于多種類(lèi)型,比較運(yùn)算符根據(jù)下表比較(按順序)。

比較多種類(lèi)型
運(yùn)算數(shù) 1 類(lèi)型 運(yùn)算數(shù) 2 類(lèi)型 結(jié)果
nullstring string null 轉(zhuǎn)換為 "",進(jìn)行數(shù)字或詞匯比較
boolnull 任何其它類(lèi)型 轉(zhuǎn)換為 bool,false < true
object object 內(nèi)置類(lèi)可以定義自己的比較,不同類(lèi)不能比較,相同類(lèi)和數(shù)組同樣方式比較屬性(PHP 4 中),PHP 5 有其自己的說(shuō)明
string、resource、int、float stringresource、intfloat 將字符串和資源轉(zhuǎn)換成數(shù)字,按普通數(shù)學(xué)比較
array array 具有較少成員的數(shù)組較小,如果運(yùn)算數(shù) 1 中的鍵不存在于運(yùn)算數(shù) 2 中則數(shù)組無(wú)法比較,否則挨個(gè)值比較(見(jiàn)下例)
object 任何其它類(lèi)型 object 總是更大
array 任何其它類(lèi)型 array 總是更大

示例 #1 Boolean/null comparison

<?php
// Bool 和 null 總是作為 bool 比較
var_dump(== TRUE);  // TRUE - same as (bool)1 == TRUE
var_dump(== 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, -10NULL10100)); // NULL - (bool)NULL < (bool)-100 is FALSE < TRUE
?>

示例 #2 標(biāo)準(zhǔn)數(shù)組比較代碼

<?php
// 數(shù)組是用標(biāo)準(zhǔn)比較運(yùn)算符這樣比較的
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 
null// uncomparable
        
} elseif ($val $op2[$key]) {
            return -
1;
        } elseif (
$val $op2[$key]) {
            return 
1;
        }
    }
    return 
0// $op1 == $op2
}
?>

警告

比較浮點(diǎn)數(shù)

由于浮點(diǎn)數(shù) float 的內(nèi)部表達(dá)方式,不應(yīng)比較兩個(gè)浮點(diǎn)數(shù)float是否相等。

更多信息參見(jiàn) float

三元運(yùn)算符

另一個(gè)條件運(yùn)算符是“?:”(或三元)運(yùn)算符 。

示例 #3 賦默認(rèn)值

<?php
// 三元運(yùn)算符的例子
$action = (empty($_POST['action'])) ? 'default' $_POST['action'];

// 以上等同于以下的  if/else 語(yǔ)句
if (empty($_POST['action'])) {
    
$action 'default';
} else {
    
$action $_POST['action'];
}

?>
表達(dá)式 (expr1) ? (expr2) : (expr3)expr1 求值為 true 時(shí)的值為 expr2,在 expr1 求值為 false 時(shí)的值為 expr3。

可以省略三元運(yùn)算符中間那部分。表達(dá)式 expr1 ?: expr3expr1 求值為 true 時(shí)返回 expr1,否則返回 expr3。

注意: 注意三元運(yùn)算符是個(gè)語(yǔ)句,因此其求值不是變量,而是語(yǔ)句的結(jié)果。如果想通過(guò)引用返回一個(gè)變量這點(diǎn)就很重要。在一個(gè)通過(guò)引用返回的函數(shù)中語(yǔ)句 return $var == 42 ? $a : $b; 將不起作用,以后的 PHP 版本會(huì)為此發(fā)出一條警告。

注意:

建議避免將三元運(yùn)算符堆積在一起使用。和其他語(yǔ)言相比, 當(dāng)在單個(gè)表達(dá)式中使用多個(gè)未加括號(hào)的三元運(yùn)算符時(shí)會(huì)造成 PHP 運(yùn)算結(jié)果不清晰。 甚至在 PHP 8.0.0 之前,三元運(yùn)算符是從左到右執(zhí)行的, 而大多數(shù)其他編程語(yǔ)言是從右到左的。 自 PHP 7.4.0 起,棄用依靠左聯(lián)。 PHP 8.0.0 起,三元運(yùn)算符是非關(guān)聯(lián)的。

示例 #4 不清晰的三元運(yùn)算符行為

<?php
// 乍看起來(lái)下面的輸出是 'true'
echo (true 'true' false 't' 'f');

// 然而,上面語(yǔ)句的實(shí)際輸出是't',因?yàn)樵?nbsp;PHP 8.0.0 之前三元運(yùn)算符是左聯(lián)的

// 下面是與上面等價(jià)的語(yǔ)句,但更清晰
echo ((true 'true' 'false') ? 't' 'f');

// 這里可以看到第一個(gè)表達(dá)式的計(jì)算結(jié)果是 “true”,第二個(gè)表達(dá)式的計(jì)算結(jié)果為 (bool)true,
// 因此返回第二個(gè)三元表達(dá)式的 true 分支。
?>

NULL 合并運(yùn)算符

而且存在 "??" (NULL 合并)運(yùn)算符。

示例 #5 設(shè)置默認(rèn)值

<?php
// NULL 合并運(yùn)算符的例子
$action $_POST['action'] ?? 'default';

// 以上例子等同于于以下 if/else 語(yǔ)句
if (isset($_POST['action'])) {
    
$action $_POST['action'];
} else {
    
$action 'default';
}

?>
當(dāng) expr1null,表達(dá)式 (expr1) ?? (expr2) 等同于 expr2,否則為 expr1。

尤其要注意,當(dāng)不存在左側(cè)的值時(shí),此運(yùn)算符也和 isset() 一樣不會(huì)產(chǎn)生警告。 對(duì)于 array 鍵尤其有用。

注意: 請(qǐng)注意:NULL 合并運(yùn)算符是一個(gè)表達(dá)式,產(chǎn)生的也是表達(dá)式結(jié)果,而不是變量。 返回引用變量時(shí)需要強(qiáng)調(diào)這一點(diǎn)。 因此,在返回引用的函數(shù)里就無(wú)法使用這樣的語(yǔ)句:return $foo ?? $bar;,還會(huì)提示警告。

注意:

請(qǐng)注意,NULL 合并運(yùn)算符支持簡(jiǎn)單的嵌套:

示例 #6 嵌套 NULL 合并運(yùn)算符

<?php

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

echo 
$foo ?? $bar ?? $baz ?? $qux// 輸出 1

?>