【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文の条件と同じで、0
やnull
等かそうでないかで決まります。
$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
ではない場合は左辺の値を返す、ということです。ここで、0
やfalse
などの場合はnull
として扱われません。
特定の値かを判定する関数
null
かどうか、配列かどうかなど、一部の判定は関数を使うという方法があります。
$a = ["foo" => 100, "bar" => 200]; if (isset($a["hoge"])) { print("hogeは無いので実行されない"); }
以下のような関数があります。
関数 | 意味 |
---|---|
isset | 変数があるかどうか。初期化されていない変数や、配列に存在しないなどはissetがfalseになる。null が入っていても存在する変数ならtrue になる。また、存在しない変数を指定しても警告は出ない。 |
is_null | null かどうか。存在しない変数や配列のインデックスを指定した場合はis_null を満たすが、警告が出る。 |
is_array | 配列や連想配列かどうか。空の配列でも満たす。 |
is_numeric | 数値かどうか。"100" のように文字列の中身が数値の場合、is_numeric を満たす。主に文字列の中身が数値かどうかの判定に用いる。 |
empty | 空かどうか。== false と実質同じであるため、型の扱いに注意が必要。 |
is_string | 文字列かどうか。 |
is_int | 整数かどうか。0.0 のように.0 となっていても型は実数であり、整数ではないことに注意が必要。 |
特によく使用するのはisset
やis_null
あたりです。isset
とis_null
の大きな違いは、未定義の変数や、配列で存在しないインデックスを入れたときに警告が出るかどうかにあります。つまり、存在するかどうかを知りたいならisset
を、値があること前提でnull
かどうかを知りたいならis_null
を使う、ということになります。
まとめ
PHPにおけるif文では、型の扱いに注意が必要です。等しいかどうかを調べる際は、基本的に厳密等価演算子を使うべきです。
isset
やis_array
といった関数、null合体演算子などを駆使して書いてくと、見やすいコードに繋がります。
