【PHP】 if文の注意点やnull合体演算子などを知る

PHPのif文や比較演算子、論理演算子の文法は他言語と変わりません。しかし、動的型付け言語特有のfalse周りの処理に大きな課題があります。

if文の書き方

PHPのif文は、多くの言語に見られる文法と同じです。

$a = 100;
if ($a == 100) {
    // 実行される
    print("\$aは100");
}
else if ($a > 0) {
    print("\$aは0より上");
}
else {
    print("\$はその他の値");
}

比較演算子

他言語とおおよそ同じですが、型も比較する厳密等価演算子が追加されています。

演算子意味
==等しい (型の扱いに注意が必要)
> >= < <=左辺が右辺より大きい、以上、未満、以下
!=左辺と右辺が異なる (型の扱いに注意が必要)
===左辺と右辺の値と型が等しい
!==左辺と右辺の値と型のいずれかが異なる

== と !=

PHPの==は、自動的に型が変換されて比較されます。例えば0 == falseは型が整数と論理値で異なりますが、比較時は自動的に型が合わさり (変換できる場合)、比較されます。

複雑なため、よほどのことがない限り厳密等価演算子を使うべきです。

if (0 == false) {
    print(true);
}

if ("0" == 0) {
    print(true);
}

if ("000.0" == 0) {
    print(true);
}

if (0.0 == 0) {
    print(true);
}

if ("123" == 123) {
    print(true);
}

if (false == null) {
    print(true);
}

if (0 == null) {
    print(true);
}

if ("1" == true) {
    print(true);
}

if ("1000" == true) {
    print(true);
}

// 等しくないのはこれだけ
if ("0" == null) {
    print(false);
}
  • 文字列と数値の比較は、文字列が数値でできている場合に数値として比較。ただし、文字列を16進数として書いても数値扱いにはならない。("0xff"など)
  • ほとんどの文字列とbooleanの比較は文字列がtrue扱い、"0"""false扱いになる。ここで、"00""0.0""\0"true扱い
  • "0" == falseは等しい扱いだが、"0" == nullは等しくない扱い。しかし0 == nullは等しい扱い
  • 空の配列は[] == falseは等しい扱いだが、[] == 0は等しくない扱いになる
  • etc…

あまりにも複雑でバグの温床となるため、使うべきではありません。

厳密等価演算子

===!==は、型も含めて比較します。基本的にはこちらを使うべきです。

if (0 === 0) {
    print(true);
}

if ("0" === 0) {
    print(false);
}

if (0.0 === 0) {
    print(false);
}

if (0 === false) {
    print(false);
}

if (1 === true) {
    print(false);
}

if ([1, 2, 3] === [1, 2, 3]) {
    print(true);
}

if (function () {} === function () {}) {
    print(false);
}

if ("0.0" !== 0.0) {
    print(true);
}

このように、==!=では型が変換されて比較していたのが、こちらではそうではないことが分かります。

型には整数、実数、論理値、文字列、配列等に分類されています。整数と実数は別の型であることに注意が必要です。

論理演算子

これも多くの言語の使用と共通しています。

演算子意味
&&論理積
||論理和
!NOT (単項演算子)

ただし、PHPには||=&&=といった、+=と同じような省略形の代入はありません。

三項演算子

PHPでは、他言語にあるような?:を使った三項演算子を利用できます。

条件文 ? trueの場合の内容 : falseの場合の内容というふうに書きます。また、条件の部分はif文の条件と同じで、0null等かそうでないかで決まります。

$a = 100;
$b = $a === 100 ? "aは100" : "aは100ではない";
print($b); // aは100

null合体演算子

isset($a["hoge"]) ? 100 : $a["hoge"]のように、配列でそのインデックスがあればそれを使い、なければ特定の値を使う、といったことはよくあります。この場合、null合体演算子 (??) を使うとスマートに書くことができます。

$a = ["foo" => 100, "bar" => 200];

$b = $a["foo"] ?? 500; // $a["foo"]はnullではない
$c = $a["hoge"] ?? 500; // $a["hoge"]はnull
$d = $a["baz"] ?? 1000; // nullの場合は右辺の値が使われる

print("$b $c $d"); // 100 500 1000

つまり、??の左辺がnullの場合は右辺の値を、nullではない場合は左辺の値を返す、ということです。ここで、0falseなどの場合はnullとして扱われません。

特定の値かを判定する関数

nullかどうか、配列かどうかなど、一部の判定は関数を使うという方法があります。

$a = ["foo" => 100, "bar" => 200];
if (isset($a["hoge"])) {
    print("hogeは無いので実行されない");
}

以下のような関数があります。

関数意味
isset変数があるかどうか。初期化されていない変数や、配列に存在しないなどはissetがfalseになる。nullが入っていても存在する変数ならtrueになる。また、存在しない変数を指定しても警告は出ない。
is_nullnullかどうか。存在しない変数や配列のインデックスを指定した場合はis_nullを満たすが、警告が出る。
is_array配列や連想配列かどうか。空の配列でも満たす。
is_numeric数値かどうか。"100"のように文字列の中身が数値の場合、is_numericを満たす。主に文字列の中身が数値かどうかの判定に用いる。
empty空かどうか。== falseと実質同じであるため、型の扱いに注意が必要。
is_string文字列かどうか。
is_int整数かどうか。0.0のように.0となっていても型は実数であり、整数ではないことに注意が必要。

特によく使用するのはissetis_nullあたりです。issetis_nullの大きな違いは、未定義の変数や、配列で存在しないインデックスを入れたときに警告が出るかどうかにあります。つまり、存在するかどうかを知りたいならissetを、値があること前提でnullかどうかを知りたいならis_nullを使う、ということになります。

まとめ

PHPにおけるif文では、型の扱いに注意が必要です。等しいかどうかを調べる際は、基本的に厳密等価演算子を使うべきです。

issetis_arrayといった関数、null合体演算子などを駆使して書いてくと、見やすいコードに繋がります。

php if thumb

役に立ったらシェアしよう!