3
0

More than 3 years have passed since last update.

PHP8.0からはin_arrayの第3引数のtrueを付け忘れても、意図しない挙動が防げるようになる

Last updated at Posted at 2020-11-15

TL;DR

<?php

$hogeArray = ["hoge", "foo", "bar"];

// PHP 7まで
in_array(0, $hogeArray); // true(意図しない挙動)

in_array(0, $hogeArray, true); // false

// PHP 8
var_dump(in_array(0, $hogeArray)); // false

PHP 8からは、in_arrayの第三引数を省略しても、上記のような意図しない挙動が防げるようになる。

背景

非厳密な比較演算子==の挙動が変更になる

2020/11/26より、PHPの5年ぶりの時期メジャーバージョンアップであるPHP 8がリリースされます。JITなど、重要なRFCが目白押しですが、その中に「非厳密な比較演算子 == の挙動が変更になる」というものがあります。

詳しくは、PHP RFC: Saner string to number comparisons や、他の方が書かれた分かりやすい記事【PHP8.0】非厳密な比較演算子==の挙動が今さら変更になるをご参照ください。

本記事の主題に入る前に、非厳密な比較演算子==の挙動の変更について述べる必要があるため、ざっくりと説明します。


数値(例:0)と数値文字列(例:"0")を非厳密演算子 == で比較する場合、数値文字列は数値に変換されて文字列比較されます。

php8以前
<?php
0 == "0"; // true

それ以外の場合(例:数値と数値文字列以外の文字列の比較)は、文字列を数値に変換して比較します。数値文字列以外の文字列を数値へ変換した場合は 0 になるので、以下の結果になります。

php8以前
<?php
0 == "hoge"; // true

しかし、PHP 8へのメジャーバージョンアップデートによって、 == の挙動が変わります。
数値文字列以外の文字列と数値を比較する場合は、数値を文字列に変換してから、文字列比較するようになります。

php8
<?php
0 == "hoge"; // false

in_arrayの挙動が変わる

本記事の主題です。

非厳密な比較演算子 == の挙動の変更により、in_arrayの挙動も変更となります。

in_arrayは、第3引数でstrictが設定されていない限りは型の比較は行いません。つまり、 == を使って比較しています。

そのため、今までは意図しない挙動を予防するために、in_arrayの第3引数には true をつける必要がありました。

参考:in_arrayを使うときは黙って第三引数を付けること

ですが、今回のPHP 8へのメジャーバージョンアップデートによって、== の挙動が変更になったことにより第3引数にtrueを付けなくとも、意図しない挙動が起きなくなります。

php8
<?php

$hogeArray = ["hoge", "foo", "bar"];
in_array(0, $hogeArray); // false

さいごに

PHP 8の登場により、非厳密な比較演算子 == での比較はより安全になりました。
以下に示した例で、$needleSample0 などになっているエッジケースが起こった場合にin_arrayの第3引数を付け忘れていたことで、問題の特定に開発者が頭を抱えることが少なくなりそうです。


<?php

$hogeArray = ["hoge", "foo", "bar"];

if (in_array($needleSample, $hogeArray)) {
  // なんかの処理
}

注意: この記事は == での比較が今までより安全になったから、これからはin_arrayの第3引数の省略をとにかく推奨する内容ではありません。

自分の調べた範囲では、第3引数を省略しても、今まで発生していた意図しない挙動を防ぐことを確認できましたが、調査し切れておらず防げないパターンがあるかもしれません**(是非ご指摘ください:qiitan:)**。

よって、第3引数を省略して、業務コーディング中に防げないパターンについてあれこれ考察するのは時間を浪費です。乱暴な言い方ですが、これからも困ったら第3引数のstructtrueにしておけば安定です。

補足(2020/11/26まで)

メジャーアップデートは2020/11/26ですが、その前にPHP 8の挙動を確認したい方は、

PHP 8.0のイメージをpullしてこればカレントディレクトリにPHPファイルを置いて、以下のようにPHP 8環境で挙動を試すことができます。

docker run --rm -v `pwd`:/app -w /app php:8.0-rc php php8test.php

参考情報

3
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
0