streamDownload を使って CSV をダウンロードするサンプルです。Controller の処理だけ書いておきます。
(簡単なサンプルなので、諸々抜けています。)
controller
public function csvDownload()
{
return response()->streamDownload(function () {
$handle = fopen('php://output', 'w');
$list = [[1,'hoge'], [2,'piyo'], [3, 'fuga']];
foreach ($list as $row) {
fputcsv($handle, $row);
}
fclose($handle);
}, 'sample.csv');
}
公式ドキュメント => https://laravel.com/docs/6.x/responses#file-downloads
以下のような CSV がダウンロードされる。
おわり。
補足1
以下のようにもかけるけど、結局 fpassthru で output buffer に渡しているので、あまり変わらないような気がする。けど、まだよくわかっていない。php://outpt
と php://memory
php://temp
の使い分けが全然わかっていない。勉強が必要!
controller
return response()->streamDownload(function () {
$handle = fopen('php://temp', 'w'); // temp に変更
$list = [[1,'hoge'], [2,'piyo'], [3, 'fuga']];
foreach ($list as $row) {
fputcsv($handle, $row);
}
rewind($handle); // 追記
fpassthru($handle); // 追記
fclose($handle);
}, 'sample.csv');
cf. https://stackoverflow.com/questions/5946526/having-problems-reading-writing-the-php-temp-stream
補足2
Content-Type が text/html だった。text/csv にしておきたい気持ちがある。
補足3
Windows だと日本語文字化けします。
var_dump
$handle = fopen('php://memory', 'w');
$list = [[1,'hoge'], [2,'piyo'], [3, 'fuga']];
foreach ($list as $row) {
fputcsv($handle, $row);
}
rewind($handle);
// fpassthru($handle); // これをした後だと、stream_get_contents に入ってこない。
var_dump(stream_get_contents($handle));
fclose($handle);
こんな感じでデバッグをして。文字コードを変更するバージョンは以下です。
抜粋
return response()->streamDownload(function () use ($header, $list) {
$handle = fopen('php://temp', 'w');
fputcsv($handle, $header);
foreach ($list as $row) {
fputcsv($handle, $row);
}
rewind($handle);
echo mb_convert_encoding(stream_get_contents($handle), 'SJIS-win', 'UTF-8');
fclose($handle);
}, $name);