PHPでin_arrayを行った際、連想配列の挙動に戸惑った話

この記事を書いたチーム:frontier
PHPでin_arrayを行った際、連想配列の挙動に戸惑った話

結論 

【エンジニア募集中】フルリモート可◎、売上/従業員数9年連続UP、平均残業8時間、有給取得率90%、年休124日以上 etc.  詳細はこちらから>

連想配列のキー値が1~9で始まる場合、数値型のキーが設定されているため、連想配列のキー検索等でin_arrayを行う際、型を統一しないとin_arrayで厳密比較が行えなくなる。

前提条件と発生した内容 

以下のようなデータを用いて、DBのポイント残高を更新していました。 

<DB登録済みデータ> 

会員ID(int) 

検索用ID(String) 

最終利用日時(Date) 

1 

0001 

2023/09/10 

2 

1001 

2023/10/20 

3 

1002 

2022/12/21 

4 

2001 

2023/10/01 

 

<外部取得データ> 

検索用ID(String) 

利用日時(Date) 

購入情報(String) 

0001 

2023/10/10 

XXXXXXXXXX 

1002 

2023/10/23 

XXXXXXXXXXXX 

1001 

2023/09/30 

XXXXXXXXXXXXXXXX 

 

それぞれの検索用IDを比較し、DB登録済みデータと紐づく外部取得データが存在する場合、DBの最終利用日時を外部取得データの利用日時に更新していました。 

サンプルコード: 

ところがPHPのバージョンを7から8に更新した後、客先から「検索用IDが「0001」以外の利用日時が更新されない」と連絡が来たため、原因の調査と解決法を調べました。 

原因 

  • 連想配列のキー値の先頭が1~9の場合、キーがint型になる仕様であった。
  • PHPが7から8に更新した影響で、in_arrayの型比較を厳密比較で行うよう変更していた※PHP7の段階では緩やかな比較であったため、発生していなかった。

対策 

in_array関数周りを以下のように変更しました。

まとめ 

PHPは変数に値を設定する際に型を意識しないため、値を代入した際どのような型が格納されているか、都度確認しなければならないと感じました。 

また、今回は連想配列キーの型を変更しましたが、初めからAPI取得側を連想配列としておけば出ない問題でした。プログラムを作成する際、代案がないか、最適なコードとなるのか…特に新規作成を行う場合、慎重に判断しなければいけないなと改めて思いました。 

【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>

Smallitのサービス