比較演算子
比較演算子は、その名前が示すように、二つの値を比較します。 型の比較表 に、型に関連するさまざまな比較の例があります。
例 | 名前 | 結果 |
---|---|---|
$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 が
|
オペランドが両方
数値形式の文字列 の場合、
もしくは一方が数値で、もう一方が
数値形式の文字列 の場合、
比較は数値として行われます。
これらのルールは
switch 文にも適用されます。
型の変換は
演算子が ===
や !==
の場合は行われません。
なぜなら、これらの演算子は、値と型を両方比較するものだからです。
警告 PHP 8.0.0 より前のバージョンでは、 文字列が数値または数値形式の文字列の場合、文字列は比較する前に数値に変換されていました。 これによって、以下の例で見られるような驚きの結果が生じる場合があります:
<?phpvar_dump(0 == "a"); // 0 == 0 -> truevar_dump("1" == "01"); // 1 == 1 -> truevar_dump("10" == "1e1"); // 10 == 10 -> truevar_dump(100 == "1e2"); // 100 == 100 -> trueswitch ("a") {case 0: echo "0"; break;case "a": // "a" は 0 にマッチするので、決してここにはたどりつきません echo "a"; break;}?>
<?php // Integerecho 1 <=> 1; // 0echo 1 <=> 2; // -1echo 2 <=> 1; // 1 // Floatecho 1.5 <=> 1.5; // 0echo 1.5 <=> 2.5; // -1echo 2.5 <=> 1.5; // 1 // 文字列echo "a" <=> "a"; // 0echo "a" <=> "b"; // -1echo "b" <=> "a"; // 1 echo "a" <=> "aa"; // -1echo "zz" <=> "aa"; // 1 // 配列echo [] <=> []; // 0echo [1, 2, 3] <=> [1, 2, 3]; // 0echo [1, 2, 3] <=> []; // 1echo [1, 2, 3] <=> [1, 2, 1]; // 1echo [1, 2, 3] <=> [1, 2, 4]; // -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 または string | string | null を "" に変換し、数値または文字として比較します
|
bool または null | あらゆる型 | 両辺を bool に変換し、false < true と判断します
|
object | object | 組み込みクラスには独自の比較基準が定義されています。
異なるクラスは比較できません。同じクラスであるかどうかは ここで説明されています。 |
string, resource, int または float | string, resource, int または float | 文字列やリソースを数値に変換し、算術演算を行います |
array | array | 要素数の少ない配列のほうが小さくなります。オペランド 1 のキーが
オペランド 2 に存在しない場合、配列は比較できません。そうでない場合は 個々の要素の値を比較します(以下の例を参照ください) |
object | あらゆる型 | object のほうが常に大きくなります |
array | あらゆる型 | array のほうが常に大きくなります |
例1 Boolean/null comparison
<?php// Bool and null are compared as bool alwaysvar_dump(1 == TRUE); // TRUE - same as (bool)1 == TRUEvar_dump(0 == FALSE); // TRUE - same as (bool)0 == FALSEvar_dump(100 < TRUE); // FALSE - same as (bool)100 < TRUEvar_dump(-10 < FALSE);// FALSE - same as (bool)-10 < FALSEvar_dump(min(-100, -10, NULL, 10, 100)); // 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)
という式は、式1 が true
の場合に
式2 を、
式1 が false
の場合に
式3 を値とします。
三項演算子のまんなかの部分をなくすこともできます。
式 expr1 ?: expr3
の結果は、expr1 が
true
と同等の場合は expr1、
それ以外の場合は expr3 となります。
注意:
三項演算子は式であり、値としては評価されずに式の結果として評価される ことに注意してください。演算結果をリファレンスとして返したい場合に、 これを知っておくことが大切です。結果をリファレンスとして返す関数で
return $var == 42 ? $a : $b;
とすることはできず、 警告が発生します。
注意:
三項演算子を "積み重ねて" 使用することは避けましょう。 ひとつの文の中で複数の三項演算子を使用した際の PHP の振る舞いは、 他のプログラミング言語のそれと比べて、少々わかりにくいものです。 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)
は、
expr1 が null
である場合は 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 です?>