LoginSignup
298
181

More than 5 years have passed since last update.

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

Posted at

はじめに

  • phpでin_array使ってますか?
  • その時、第3引数って使ってますか?
  • 使ってない?いつ事故ってもおかしくないですよ?

まずは普通に使ってみる

<?php

$students = ['山本', '山下', '山田'];

var_dump(in_array('山田', $students)); // trueを返すはず
var_dump(in_array('山原', $students)); // falseを返すはず

実行してみましょう。山原さんは$studentsにいないのでfalse返すはずですよね。

$ php test.php
bool(true)
bool(false)

はい。想定通りですね。

じゃあ問題です

<?php

$numbers = [0, 1, 2, 3, 4, 5];

var_dump(in_array(3,      $numbers)); // trueを返すはず
var_dump(in_array('山原', $numbers)); // falseを返すはず

さぁ、どうなるでしょうか?

$ php test.php
bool(true)
bool(true)

なんという事でしょう!!
山原なんて文字列は$numbersに含まれてないのにtrueを返してきました。

一体何が起きたのか

マニュアルを読んで見ましょう。

bool in_array ( mixed $needle , array $haystack [, bool $strict = FALSE ] )


needle で haystack を検索します。 strict が設定されていない限りは型の比較は行いません。

なんという事でしょう。
第三引数のstrictはデフォルトでfalseになっているため、型比較までしない。
つまり、==で比較してるわけですね。

これがPHPの悲しい所ですが、1つ簡単な実験をします。

<?php

var_dump('山原' == 0);
var_dump('山原' === 0);

さぁ、これはどうなるでしょうか。両方falseになると思いがちですよね。

$ php test.php
bool(true)
bool(false)

なんと・・・

これがPHPな訳です。

答えは、比較演算子に書いてあります。

例 名前  結果
$a == $b    等しい   型の相互変換をした後で $a が $b に等しい時に TRUE。

型の相互変換をした後でとありますね。

つまり、これが暗黙の型変換ってやつで、文字列と数値を比較する場合には暗黙の間に文字列の型変換が行われて0になってしまうのです。
怖いかもしれませんが仕様です。

じゃあどうすればよいのか?

答えですが、in_array使うときは黙って第三引数にtrueを指定しなさいです。

元のコードに戻って、in_arrayの第三引数にtrueを指定して型までチェックさせてみます。

<?php

$numbers = [0, 1, 2, 3, 4, 5];

var_dump(in_array(3,      $numbers, true)); // trueを返すはず
var_dump(in_array('山原', $numbers, true)); // falseを返すはず

いざ・・!

$ php test.php
bool(true)
bool(false)

ようやく想定どおりの結果になりました。

PHPでは色んな罠がありますが、これも一種です。
サーバアプリケーションでは、受け取った値を元にバリデーションするシーンで使う機会は多いと思います。
そんな時に通っちゃいけない文字列が通るという危険なバグになりかねないです。

最後にもう一度

in_array使うときは黙って第三引数にtrueを指定しなさい

以上です。

298
181
3

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
298
181