CSVエクスポートでLaravelが用意するStorageクラスでファイル作成してループして1行ずつ書き込みすると無茶苦茶重いというか時間がかかったのでもっと早く出来ないかと調べた結果をメモ。
参考サイト
【PHP】大量データをfputcsvで瞬時にCSVファイル出力する方法
環境
FW: Laravel 6.x
PHP: 7
どのぐらい早いか
条件
レコード数: 50,000件
テーブルデータサイズ : 5.4MB
※PCのスペックとかもあるだろうけど、開発環境はDocker for Mac使っています。
結果
実行時間1回目: 16.8 sec
実行時間2回目: 25.2 sec
サンプルコード
UserController.php
public function export() {
$users = new App\User::all();
$filePath = storage_path(sprintf('app/%s.csv', date('ymd_hisu')));
$stream = fopen('php://temp', 'w');
$header = $users->first()->getFillable();
mb_convert_variables('SJIS-win', 'UTF-8', $header);
fputcsv($stream, $header);
foreach ($users as $user) {
$line = $user->toArray();
mb_convert_variables('SJIS-win', 'UTF-8', $line);
fputcsv($stream, $line);
}
rewind($stream);
$content = stream_get_contents($stream);
file_put_contents($filePath, $content);
fclose($stream);
return response()
->download($filePath, sprintf('サンプル%s.csv', now()->format('YmdHis')))
->deleteFileAfterSend();
}