CSV出力する際に、値をダブルクォーテーションで囲うに必要があった。
PHP標準のfputcsvではバグがありました。
$enclosureに設定しても間に空白がある文字列しかダブルクォーテーションで囲んでくれない。 fputcsvを使う前に
"を付けると
"""と出力してしまう。 これはエスケープ
"`しても起きる。
結局自作した。
動作確認環境
- PHP 7.3
値をダブルクォーテーションで囲ってCSV形式にする
下の関数で2次元配列のデータをCSV形式にして出力できる。
/**
* CSV形式に変換
* @param array $data 2次元配列
* @return string $csv
*/
function tocsv($data, $toEncoding='sjis-win', $srcEncoding='UTF-8') {
$csv = '';
foreach ($data as $row) {
// ダブルクォーテーションで囲う
$row = array_map(function($value){return "\"{$value}\"";}, $row);
// カンマ区切り
$row = implode(',', $row);
$csv .= $row . "\r\n";
}
$csv = mb_convert_encoding($csv, $toEncoding, $srcEncoding);
return $csv;
}
処理が簡潔になるよう行を一括して整形している。
array_map
で配列の値をダブルクォーテーションで囲うimplode
で1行をカンマ区切の文字列に結合する- Windowsに対応した改行文字を末尾に付けて、$csv`に追加
また、Excelで開いたときに文字化けしないようにsjis-win
にエンコーディングしている。
この後、ファイルに保存するなり、ダウンロードのさせるなりしても値をダブルクォーテーションで囲ったCSVができる。
LaravelでCSVダウンロード
Laravelの\Illuminate\Http\Response
を使ってCSVダウンロードを実装した例。
これをControllerで返してあげる。
/**
* CSVダウンロード
* @param array $list
* @param array $header
* @param string $filename
* @return \Illuminate\Http\Response
*/
public function download($list, $header, $filename)
{
if (count($header) > 0) {
array_unshift($list, $header);
}
$csv = $this->tocsv($list);
$headers = array(
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename=$filename",
);
return \Response::make($csv, 200, $headers);
}
正直言うとExcelで見る際にダブルクォーテーションで囲う必要性は薄い。 ゼロ埋めした数値をそのまま表示したいときぐらい。
参考
- fputcsv
- [PHP] fputcsv関数の問題点と解決方法 - TechRacho
- 同じようにfputcsvのバグに悩まされていた。
- 【PHP】csvを自前で作った話 | ダブルコーテーション問題でfputcsvは使わず実装
laravel newコマンドでbash:laravel:command not found
Laravelschedule2020-10-05
LaravelのModelsのディレクトリ構成を変更する
Laravelschedule2020-09-02
【Laravel】UserAgentでガラケー用のViewを切り替えるためのmiddleware
Laravelschedule2020-04-21
PHP Warning Illegal string offset 'foo'
PHPschedule2020-02-03