PHP CSVの1行目をキー、2行目以降を値にした連想配列を作りたい
例えば以下のようなCSVデータがあって、
"name","email" "Sato Asuka","satoasuka@example.com" "Goto Yousuke","yousukegoto@example.net" "Fujita Takahiro","takahiro_fujita@example.org"
下記のような形にして扱えるようにしたいということです。
<?php [ [ 'name' => 'Sato Asuka', 'email' => 'satoasuka@example.com', ], [ 'name' => 'Goto Yousuke', 'email' => 'yousukegoto@example.net', ], [ 'name' => 'Fujita Takahiro', 'email' => 'takahiro_fujita@example.org', ], ];
1. CSVファイルの読み取り
ファイル読み取りは内部関数・ファイル操作クラスを使った方法がありますが、 CSVの場合は後者のほうがスムーズなようです。
<?php $file = new SplFileObject('./dummy.csv'); // CSVを読み取るためのオプションを指定 $file->setFlags( SplFileObject::READ_CSV // CSV形式のファイルを読み込む | SplFileObject::DROP_NEW_LINE // 行末の改行を削除 | SplFileObject::READ_AHEAD // 先読み・巻き戻しで読み出す(?) | SplFileObject::SKIP_EMPTY // 空行をスキップする。 READ_AHEADの指定がないと無効 );
READ_AHEAD
オプションについてはよくわかりませんでした…。(どこを見ても「先読み・巻き戻し」としか書いてない)
SplFileObjectクラスはIteratorインターフェースを実装しているため、 foreachでループさせることができます。
<?php // 1行ずつループ処理 foreach ($file as $line) { mb_convert_variables('UTF-8', 'SJIS-win', $line); // 任意:CSVはSJISで保存されていることが多く、その場合UTF-8への変換が必要 print_r($line); }
■結果
Array ( [0] => name [1] => email ) Array ( [0] => Sato Asuka [1] => satoasuka@example.com ) Array ( [0] => Goto Yousuke [1] => yousukegoto@example.net ) Array ( [0] => Fujita Takahiro [1] => takahiro_fujita@example.org )
とりあえず配列として取り出すことができました。
2. キーの配列と値の配列に分ける
ループの1番目がキーにしたい行なので、インデックスを指定すれば分けられそうです。
<?php $keys = []; $userList = []; foreach ($file as $i => $line) { mb_convert_variables('UTF-8', 'SJIS-win', $line); if ($i === 0) { $keys = $line; } else { $userList[] = $line; } } print_r($keys); print_r($userList);
■結果
Array ( [0] => name [1] => email ) Array ( [0] => Array ( [0] => Sato Asuka [1] => satoasuka@example.com ) [1] => Array ( [0] => Goto Yousuke [1] => yousukegoto@example.net ) [2] => Array ( [0] => Fujita Takahiro [1] => takahiro_fujita@example.org ) )
問題なく分けられました。
3. 2.で得られた配列から、表題の連想配列を作成する
「2つの配列をキー、値にして一つにする関数とかありそうだな。PHP死ぬほど関数あるし」と思ってたらありました。
キーと値の要素数が一致しないと配列が作成できないため、ループ内で配列を作成します。
<?php $keys = []; $userList = []; foreach ($file as $i => $line) { mb_convert_variables('UTF-8', 'SJIS-win', $line); if ($i === 0) { $keys = $line; } else { - $userList[] = $line; + $userList[] = array_combine($keys, $line); } } - print_r($keys); print_r($userList);
■結果
Array ( [0] => Array ( [name] => Sato Asuka [email] => satoasuka@example.com ) [1] => Array ( [name] => Goto Yousuke [email] => yousukegoto@example.net ) [2] => Array ( [name] => Fujita Takahiro [email] => takahiro_fujita@example.org ) )