- 開発技術
- API連携
PHPでin_arrayを行った際、連想配列の挙動に戸惑った話
- PHP
目次
結論
【エンジニア募集中】フルリモート可◎、売上/従業員数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の最終利用日時を外部取得データの利用日時に更新していました。
サンプルコード:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
<?php // ※詳細な処理は省略 // $db_data = getdataForXXXDatabase(); $db_data = []; $db_data['0001'] = ['id' => 1, 'use_date' => '2023/09/10']; $db_data['1001'] = ['id' => 2, 'use_date' => '2023/10/20']; $db_data['1002'] = ['id' => 3, 'use_date' => '2022/12/21']; $db_data['2001'] = ['id' => 4, 'use_date' => '2023/10/01']; // 検索用 $db_keys = array_keys($db_data); // 外部データを取得 $external_data = getExternalData(); foreach ($external_data as $data) { /** 今回関係あるソース */ if (in_array($data[0], $db_keys, true)) { $db_data[$data[0]]['use_date'] = $data[1]; } } // データ更新 // updateXXXData($db_data); var_dump($db_data); exit; // 外部データ取得 function getExternalData () { // $result = getDataForXXXApi(); $result = [ ['0001', '2023/10/10', 'XXXXXXXXXX'], ['1002', '2023/10/23', 'XXXXXXXXXXXX'], ['1001', '2023/09/30', 'XXXXXXXXXXXXXXXX'] ]; return $result; }; ?> |
ところがPHPのバージョンを7から8に更新した後、客先から「検索用IDが「0001」以外の利用日時が更新されない」と連絡が来たため、原因の調査と解決法を調べました。
原因
- 連想配列のキー値の先頭が1~9の場合、キーがint型になる仕様であった。
- PHPが7から8に更新した影響で、in_arrayの型比較を厳密比較で行うよう変更していた※PHP7の段階では緩やかな比較であったため、発生していなかった。
対策
in_array関数周りを以下のように変更しました。
1 2 3 4 5 6 7 |
// if (in_array($data[0], $db_keys, true)) { $comparison_key = $data[0]; if (strVal(intVal($data[0) === $comparison_key) { $comparison_key = intVal($data[0]); } if (in_array($comparison_key, $db_keys, true)) { |
まとめ
PHPは変数に値を設定する際に型を意識しないため、値を代入した際どのような型が格納されているか、都度確認しなければならないと感じました。
また、今回は連想配列キーの型を変更しましたが、初めからAPI取得側を連想配列としておけば出ない問題でした。プログラムを作成する際、代案がないか、最適なコードとなるのか…特に新規作成を行う場合、慎重に判断しなければいけないなと改めて思いました。
【エンジニア募集中】フルリモートも◎(リモート率85.7%)、平均残業8時間、年休124日以上、有給取得率90% etc. 詳細はこちらから>