PHPでCSV出力する方法で検索すると、
以下のような添字配列が例に挙がっていることが多い。
$data = array(
array('佐藤', '東京都', '29歳'),
array('田中', '千葉県', '31歳'),
array('鈴木', '北海道', '54歳')
);
ただ実際は下のようにDBから取得した連想配列をCSVで出力するケースの方が多いと思う。今回少しハマったのでメモしておく。
$assoc_data = array(
array('name' => '佐藤', 'address' => '東京都', 'old' => '29歳'),
array('name' => '田中', 'address' => '千葉県', 'old' => '31歳'),
array('name' => '鈴木', 'address' => '北海道', 'old' => '54歳')
);
連想配列のデータをCSVで出力する
全体の構成としては以下の様なコードになる。
-
連想配列で受け取ったデータをヘッダーをキーとして値のみ取得して添字配列に変換
-
各行に相当する$assoc_row[$header_name]をmb_convert_variablesでSJIS-winに変換
-
fputcsvでCSV形式に変換
-
ブラウザから直接ダウンロードさせる
$csv_header = array(
'name',
'address',
'old',
);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=data.csv');
$stream = fopen('php://output', 'w');
fputcsv($stream, $csv_header);
foreach($assoc_data as $key => $assoc_row){
$numeric_row = array();
foreach ($csv_header as $header_name) {
mb_convert_variables('SJIS-win', 'UTF-8', $assoc_row[$header_name]);
$numeric_row[] = $assoc_row[$header_name];
}
fputcsv($stream, $numeric_row);
}
SJIS-winに変換しているのは、
UTF-8のままだとエクセルで読み込んだ時に、
文字化けしてしまうのと、(株)のような機種依存文字に対応するため
他のブログとか読んでると、
mb_convert_encording
で、配列をエンコードしているコードをよく見かけるけど、
この関数は対象が文字列なのでうまく動かないはず。
なので、mb_convert_variablesで配列ごとエンコードするようにしていている。
まだ文字列中に改行コード、カンマが含まれている場合のコードは書いていないので必要になった時に追記しようと思います。
後、♥マークの文字がまだどうしても「?」になってしまって
ちゃんとエンコード出来ない。。
誰か適切な文字コードをご存知の方がいたら教えていただけると幸いです!