比較演算子

比較演算子は、その名前が示すように、二つの値を比較します。 型の比較表 に、型に関連するさまざまな比較の例があります。

比較演算子
名前結果
$a == $b等しい型の相互変換をした後で $a$b に等しい時に true
$a === $b等しい$a$b に等しく、および同じ型である場合に true
$a != $b等しくない型の相互変換をした後で $a$b に等しくない場合に true
$a <> $b等しくない型の相互変換をした後で $a$b に等しくない場合に true
$a !== $b等しくない$a$b と等しくないか、同じ型でない場合に true
$a < $bより少ない$a$b より少ない時に true
$a > $bより多い$a$b より多い時に true
$a <= $bより少ないか等しい$a$b より少ないか等しい時に true
$a >= $bより多いか等しい$a$b より多いか等しい時に true
$a <=> $b宇宙船演算子$a$b より大きいか、0か、0より小さい場合に、 それぞれ、0より大きい か、0か、0より小さい int

オペランドが両方 数値形式の文字列 の場合、 もしくは一方が数値で、もう一方が 数値形式の文字列 の場合、 比較は数値として行われます。 これらのルールは switch 文にも適用されます。 型の変換は 演算子が ===!== の場合は行われません。 なぜなら、これらの演算子は、値と型を両方比較するものだからです。

警告

PHP 8.0.0 より前のバージョンでは、 文字列が数値または数値形式の文字列の場合、文字列は比較する前に数値に変換されていました。 これによって、以下の例で見られるような驚きの結果が生じる場合があります:

<?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  
// Integer
echo <=> 1// 0
echo <=> 2// -1
echo <=> 1// 1
 
// Float
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
 
// 配列
echo [] <=> []; // 0
echo [123] <=> [123]; // 0
echo [123] <=> []; // 1
echo [123] <=> [121]; // 1
echo [123] <=> [124]; // -1
 
// オブジェクト
$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
 
// 比較するのは値だけではない; キーも一致しなければならない
$a = (object) ["a" => "b"]; 
$b = (object) ["b" => "b"]; 
echo 
$a <=> $b// 1

?>

多くの型では、以下の表にしたがって(上から順に)比較が行われます。

さまざまな型の比較
第 1 オペランドの型第 2 オペランドの型結果
null または stringstringnull を "" に変換し、数値または文字として比較します
bool または nullあらゆる型両辺を bool に変換し、false < true と判断します
objectobject組み込みクラスには独自の比較基準が定義されています。 異なるクラスは比較できません。同じクラスであるかどうかは ここで説明されています
string, resource, int または floatstring, resource, int または float文字列やリソースを数値に変換し、算術演算を行います
arrayarray要素数の少ない配列のほうが小さくなります。オペランド 1 のキーが オペランド 2 に存在しない場合、配列は比較できません。そうでない場合は 個々の要素の値を比較します(以下の例を参照ください)
objectあらゆる型object のほうが常に大きくなります
arrayあらゆる型array のほうが常に大きくなります

例1 Boolean/null comparison

<?php
// Bool and null are compared as bool always
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 一般的な配列の比較

<?php
// 標準の比較演算子を用いて、配列はこのように比較されます
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
}
?>

警告

浮動小数点数値の比較

ふたつの float 値が等しいかどうかを調べてはいけません。 float の内部的な表現方法がその理由です。

詳細な情報は float のドキュメントを参照ください。

三項演算子

もうひとつの条件演算子として "?:"(あるいは三項)演算子があります。

例3 デフォルト値を設定する

<?php
// 三項演算子の使用例
$action = (empty($_POST['action'])) ? 'default' $_POST['action'];

// 上記は以下の if/else 式と同じです。
if (empty($_POST['action'])) {
    
$action 'default';
} else {
    
$action $_POST['action'];
}

?>
(expr1) ? (expr2) : (expr3) という式は、式1true の場合に 式2 を、 式1false の場合に 式3 を値とします。

三項演算子のまんなかの部分をなくすこともできます。 式 expr1 ?: expr3 の結果は、expr1true と同等の場合は expr1、 それ以外の場合は expr3 となります。

注意: 三項演算子は式であり、値としては評価されずに式の結果として評価される ことに注意してください。演算結果をリファレンスとして返したい場合に、 これを知っておくことが大切です。結果をリファレンスとして返す関数で return $var == 42 ? $a : $b; とすることはできず、 警告が発生します。

注意:

三項演算子を "積み重ねて" 使用することは避けましょう。 ひとつの文の中で括弧で囲わずに複数の三項演算子を使用した際の PHP の振る舞いは、 他のプログラミング言語のそれと比べて、少々わかりにくいものです。 PHP 8.0.0 より前のバージョンでは、三項演算子は左から右に評価されていました。 他の殆どのプログラミング言語では、右から左に評価されます。 左から右に評価される振る舞いに依存することは、PHP 7.4.0 以降は推奨されません。 PHP 8.0.0 以降は、三項演算子はどの演算とも結合しなくなっています。

例4 三項演算子のわかりにくい挙動

<?php
// ぱっと見た感じでは、これは 'true' と表示されると思うでしょう。
echo (true 'true' false 't' 'f')

// しかし、PHP 8.0.0 より前のバージョンでは、実際には上の出力結果は 't' です。
// なぜなら、三項演算子は左結合だったからです。

// 上のコードをもう少しわかりやすく書くと、このようになります。
echo ((true 'true' false) ? 't' 'f');

// まず、最初の式が 'true' と評価されます。この 'true' は
// (bool)true と評価されるので、それをもとに二番目の三項
// 演算子が評価されます。
?>

Null 合体演算子

"??" 演算子 (null 合体演算子) を使うことが出来ます。

例5 デフォルト値の代入

<?php
// Null 合体演算子の使用例
$action $_POST['action'] ?? 'default';

// 上の文は、この if/else 文と同じ意味です
if (isset($_POST['action'])) {
    
$action $_POST['action'];
} else {
    
$action 'default';
}

?>
(expr1) ?? (expr2) は、 expr1null である場合は expr2 と評価され、それ以外の場合は expr1 と評価されます。

この演算子は、左側の値が存在しない場合でも notice や warning が発生しません。 isset() と同じ挙動です。 これは、配列のキーを扱う場合に便利です。

注意: Null 合体演算子は式であることに注意しましょう。変数として評価されるのではなく、式の結果として評価されます。 変数を参照で返そうとするときには、これを意識しておくことが重要です。 参照返しの関数で return $foo ?? $bar; のように書いてもうまく動かずに、 警告が発生します。

注意:

Null 合体演算子はネストさせることもできます。

例6 Null 合体演算子のネスト

<?php

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

echo 
$foo ?? $bar ?? $baz ?? $qux// 出力は 1 です

?>