phpの罠、連想配列のキーで厳密な比較をしてはいけない【php】

phpでは初心者のためにいくつか罠が実装されている。
以下のサンプルコードを見てほしい。実行すると何が表示されるだろうか?

<?php

// 二進数文字列を英単語に
$binaryToStr = [
  "000" => "zero",
  "001" => "one",
  "010" => "two",
  "011" => "three",
  "100" => "four",
  "101" => "five",
  "110" => "six",
  "111" => "seven",
];

// 素数には" (prime number)"をつける
$primeNumberBinaryList = ["010","011","101","111"];
foreach ($binaryToStr as $binary => $str) {
  if ( in_array($binary, $primeNumberBinaryList, true) ) {
    $binaryToStr[$binary] = $str . " (prime number)";
  }
}

// 表示する
foreach ($binaryToStr as $binary => $str) {
  print("${binary} => ${str}\n");
}

以下のように表示される事が期待動作だが、実際にはそうはならない。

000 => zero
001 => one
010 => two (prime number)
011 => three (prime number)
100 => four
101 => five (prime number)
110 => six
111 => seven (prime number)

実行してみると以下のように表示される。
なぜか、fiveとsevenが素数と判定されない。

000 => zero
001 => one
010 => two (prime number)
011 => three (prime number)
100 => four
101 => five
110 => six
111 => seven

var_dump($binaryToStr);してみると、すぐに原因が分かる。

array(8) {
  ["000"]=>
  string(4) "zero"
  ["001"]=>
  string(3) "one"
  ["010"]=>
  string(18) "two (prime number)"
  ["011"]=>
  string(20) "three (prime number)"
  [100]=>
  string(4) "four"
  [101]=>
  string(4) "five"
  [110]=>
  string(3) "six"
  [111]=>
  string(5) "seven"
}

  000~011はキーが文字列型になっているが、101~111は数値型になっている。
そのため、サンプルのように文字列型と厳密な比較を行うと偽と判定され、素数と判定されなくなる。
  なぜ、101~111のキーが数値型になるかというと、「10進数解釈できる文字列のキーは数値型に変換される」という 誰が得するのか理解に苦しむ 親切な言語仕様になっているからだ。
この仕様を回避する方法はない。(ご存じの方はコメント下さい)諦めて曖昧な比較を使って回避しよう。