PHP入門 比較演算子

左辺と右辺の値を比較し、その結果をtrue/falseとして返します。比較演算子は、if、while、do~whileのような条件分岐/繰り返し命令で条件式を表すために使用します。

主な比較演算子

演算子概要用途
==左辺と右辺の値が等しい場合はtrue7==7 結果:true
===左辺と右辺の値が等しく、かつ、同じデータ型である場合はtrue7===’7′ 結果:false
!=左辺と右辺の値が等しくない場合にtrue7!=7 結果:false
<>左辺と右辺の値が等しくない場合にtrue7<>7 結果:false
!==左辺と右辺の値が等しくない、または同じデータ型ではない場合にtrue7!==’7′ 結果:true
<左辺が右辺より小さい場合にtrue7<10 結果:true
>左辺が右辺より大きい場合にtrue7>10 結果:false
<=左辺が右辺以下の場合にtrue7<=10 結果:true
>=左辺が右辺以上の場合にtrue7>=10 結果:false
<=>宇宙船演算子。左辺が右辺より小さい場合には-1、左辺と右辺が等しい場合は0、左辺が右辺より大きい場合は17<=>10 結果:-1
?:条件演算子。「条件式?式1:式2」。条件式がtrueの場合は式1、falseの場合は式2(10>7)?’正しい’:’間違い’ 結果:正しい
??null合体演算子。左辺がnullでなければその値、左辺がnullならば右辺の値、左辺も右辺もnullの場合はnullnull ?? 10 結果:10

文字列混在の比較

等価演算子「==」は、数値と文字列を比較するときに、文字列を数値に変換した上で比較しようとします。また、文字列同士の比較であっても、数値形式の文字列である場合には、同じく数値に変換したものを比較しようとします。

PHP8前の挙動

<?php
var_dump('3.14' == 3.140000);     //結果:bool(true) ➊   
var_dump('3.14E2' == 314);        //結果:bool(true) ➋   
var_dump('0x10' == 16);           //結果:bool(false) ➌  
var_dump('010' == 8);             //結果:bool(false) ➍  
var_dump('0b11' == 3);            //結果:bool(false) ➎  
var_dump('13xyz' == 13);          //結果:bool(true) ➏
var_dump('X' == 0);               //結果:bool(true) ➐    
var_dump('3.14' == '3.14000');    //結果:bool(true) ➑
var_dump('3.14E2' == '314');      //結果:bool(true) ➒
var_dump('13xyz' == '13');        //結果:bool(false) ➓      

➊から➐は、文字列と数値の比較です。’3.14’の小数点はもちろん、’3.14E2’のような指数表記も、浮動小数点リテラルとみなされ、正しく比較されます。

➌から➎の2/8/16進数リテラルは正しく認識されません。’0x10’、’0b11’は文字列以降が切り捨てられた結果、0と見なされます。’010’はそのまま10と認識されるので、いずれも条件式はfalseとなります。

➏の数値と文字列混在は先頭の数値だけが認識されるのでtrueとなります。

➐は’X’は数値に変換するとゼロのためtrueと評価されます。

➓については、文字列同士の比較のため片方が純粋な数値文字列でない場合、数値に変換されません。したがって「’13xyz’ == ’13’」は異なる文字列とみなされ、結果はfalseとなります。

PHP8での挙動

PHP8では、➏、➐の挙動が変化し、いずれもfalseになります。

厳密な等価演算子(===)

「===」演算子は「厳密な等価演算子」と呼ばれ、値を比較する際に値とデータ型が厳密に一致するかどうかを判定します。できるだけ、「===」演算子を使用することを勧めます。

<?php
var_dump('3.14E2' == 314);     //結果:bool(false) 
var_dump('X' == 0);            //結果:bool(false)    
var_dump('1' == 1);            //結果:bool(false) ➊   

➊については、左辺/右辺とも1ですが、クォートで囲まれているため文字列リテラル、右辺は整数リテラルとみなされ、falseを返します。

浮動小数点の比較

浮動小数点は内部的に2進数として扱われるため、厳密な比較ができません。浮動小数点同士を比較する場合は、次の方法を使用します。

<?php
const EPSILON = 0.00001;
$x = 0.123456;
$y = 0.123455;
var_dump(abs($x - $y) < EPSILON );     //結果:bool(true) 

定数EPSILONは、誤差の許容範囲を表します。計算機イプシロン、丸め単位などとも呼ばれます。今回の例では、小数第5位までの精度を保証したいので、イプシロンは0.00001とします。後は、浮動小数点数同士の差を求め(absは絶対値を求める関数です)、その値がイプシロン未満であれば、保証した桁数までは等しいということになります。

配列の比較

配列同士の比較にも、「==」「===」「!=」「<>」「!==」「>」「<」「>=」「<=」演算子を利用できます。配列の比較は次の順序で行われます。

  1. 要素数で比較(要素数の少ない配列がより小さい)
  2. 要素数が等しい場合、同じキーを持つ要素同士で値の大小を比較(より大きい要素/より小さい要素がみつかったところで判定終了)
  3. 1.、2.の比較がすべて等しい場合、両者は等しいとみなされる

ただし、2で左辺の配列が持つキーを右辺の配列が持たなかった場合、比較は失敗します。

<?php
$data01 = [1, 2, 3];
$data02 = [1, 5];
var_dump($data01 < $data02);    //結果:bool(false)➊

$data11 = [1, 2, 3];
$data12 = [1, 5, 1];
var_dump($data11 < $data12);    //結果:bool(true)➋

$data11 = [1, 2, 3];
$data12 = [1, 2, '3'];
var_dump($data21 == $data22);   //結果:bool(true)➌
var_dump($data21 === $data22);  //結果:bool(false)➍

$data31 = ['A' => 'a', 'B' => 'b', 'C' => 'c'];
$data32 = ['A' => 'a', 'C' => 'c', 'B' => 'b'];
var_dump($data31 == $data32);   //結果:bool(true)➎
var_dump($data31 === $data32);  //結果:bool(false)➏
  • ➊は、$data01の要素数は$data02よりも多いので、$data01は$data02よりも大きいとみなされます。
  • ➋要素数はどちらも一緒なので、比較演算子は要素個々の大小を比較します。2番目の要素が「2<5」なので、「$data01<$data02」であると評価されます。3番目の要素「3>1」は無視されます。
  • ➌は要素数も等しく、対応する要素同士も等しいのでtrueを返します。➍は、厳密な等価演算子「===」は「3 <> ‘3’」とみなしfalseを返します。
  • ➎と➏は連想配列を「==」「===」演算子で比較したものです。$data31と$data32の違いは、要素の並び順だけです。この場合、「==」演算子はtrueを返しますが、「===」演算子はfalseを返します。厳密な等価演算子は、要素数とキ-/値の組み合わせに加えて、要素の並び順も判定の対象となります。

条件演算子(?:)

条件演算子は、指定された条件式の真偽に応じて、対応する式の値を出力します。

<?php
$score = 75;
print $score >= 70 ? '合格' : '不合格' //結果:合格
条件演算子は、オペランドを3つ必要とすることから、三項演算子と呼ばれます。オペランドを2つ必要とする「*」「/」のような演算子を二項演算子、オペランドを1つしか持たない「++」や「–」のような演算子を単項演算子と呼びます。

条件演算子の省略構文

条件演算子には、省略構文が2種類あります。

1、式1 ?: 式2

式1がtrueに変換できる場合には式1を、そうでない場合には式2を返します。省略構文は、変数が空文字列やnull、ゼロなど特殊な値を取る場合に、異なる出力をさせたいようなケースに役立ちます。

<?php
$message = '';
print $message ?: '空です。';   //結果:空です。

非省略構文

print $message ? $message : '空です。';

2、式1 ?? 式2

式1がnullでない場合には式1を、さもなければ式2を返します。null合体演算子とも呼ばれます。

<?php
//$message = 'ハロー';
print $message ?? 'ノーコメント';   //結果:ノーコメント

「?:」演算子は式1がfalseとみなせる(=空文字列やゼロ、空配列、nullなどである)場合に、式2を出力していました。しかし「??」演算子ではnullである場合にだけ式2を出力します。

非省略構文

print isset($message) ? $message : 'ノーコメント';
isset関数は、与えられた変数に値がセットされているかを判定します。(null)

条件演算子を列記する場合の注意

条件演算子を複数列記した場合の挙動は難解です。PHP7.4では推奨されておりません。また、PHP8.xではエラーとなります。

PHP7.3までの挙動

結果は「OK」となります。条件演算子は、左から順に解釈されます。

<?php
print true ? 1 : false ? 'OK' : 'NG';

よりわかりやくすカッコでまとめると以下のようになります。

<?php
print (true ? 1 : false) ? 'OK' : 'NG';

もし結果として1を期待するならば、以下のようにカッコでくくります。

<?php
print true ? 1 : (false ? 'OK' : 'NG');

条件演算子を複数列記する場合には、常にカッコでくくるのがよいでしょう。