CSVファイルを読み込んだ時って、各項目を配列にして処理したりしますよね。
で、$email = $csvData[5];
みたいにインデックス指定で値を取得したりして。
そして、ある時に突然の仕様変更。
末尾に項目が追加になれば何の問題もないんですが、途中に項目が追加されたら大変です。
今まで$csvData[5];
で取れてたemailが、$csvData[6];
になり、それ以降の項目もインデックス値が全部ズレてきてしまう。
項目数が5、6個だったらまだマシだけど、これが50個あったりすると修正ミスも起きやすいでしょう。
そこで、インデックス指定をしないで、配列から値を取得する方法を考えてみました。
環境
- php7.3
- laravel5.8
流れ
- CSVファイルの読み込みクラスを作成
- コンストラクタでインデックス変数を定義
- あとは変数を使って配列から値を取得する
具体例
public class MyCsv{
public function __construct()
{
$this->setIndex();
}
private function setIndex(){
collect([
'ID',
'NAME',
'EMAIL',
'TEL',
'ADDRESS',
])->each(function($v, $i){
//メンバー変数(配列のインデックス定数)を動的に生成。順番が大切
$this->$v = $i;
});
}
/**
* CSVの1レコードを取得してなんかやる
*
* @param array $csvRecord 1レコードのデータ配列
*/
public function logic(array $csvRecord){
$id = $csvRecord[$this->ID];
$name = $csvRecord[$this->NAME];
$email = $csvRecord[$this->EMAIL];
$tel = $csvRecord[$this->TEL];
$address = $csvRecord[$this->ADDRESS];
}
こんな感じで作っておく。
・・・そして、ある日、仕様変更がはいる。
「名前」の後ろに「ふりがな」を追加して、「電話番号」の後ろに「携帯番号」を追加するよー。
こんな時でもsetIndex()
の該当場所に項目を追加するだけで、値を取得しているコードの変更はなし。
public class MyCsv{
public function __construct()
{
$this->setIndex();
}
private function setIndex(){
collect([
'ID',
'NAME',
'KANA', //追加
'EMAIL',
'TEL',
'TEL_MOBILE', //追加
'ADDRESS',
])->each(function($v, $i){
//メンバー変数(配列のインデックス定数)を動的に生成。順番が大切
$this->$v = $i;
});
}
/**
* CSVの1レコードを取得してなんかやる
*
* @param array $csvRecord 1レコードのデータ配列
*/
public function logic(array $csvRecord){
$id = $csvRecord[$this->ID];
$name = $csvRecord[$this->NAME];
$email = $csvRecord[$this->EMAIL];
$tel = $csvRecord[$this->TEL];
$address = $csvRecord[$this->ADDRESS];
//追加で取得する項目
$kana = $csvRecord[$this->KANA];
$telMobile = $csvRecord[$this->TEL_MOBILE];
}