Edited at

LaravelでCSVダウンロード。

More than 3 years have passed since last update.


CSVダウンロード

LaravelでDBにある情報をCSVとしてダウンロードさせる。

そのときの検索結果に紐づくリストなのでCSVファイルとして保存しない。


app/routes.php

<?php

// CSVダウンロード
Route::get('/csv', function() {
$users = \User::where('type', '=', '1')->get(['name', 'birth_day'])->toArray();
$stream = fopen('php://output', 'w');
foreach ($users as $user) {
fputcsv($stream, $user);
}
$headers = array(
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="users.csv"',
);
return Response::make('', 200, $headers);
});

素直にfputcsvを使うのが良いみたいだ。


【修正】文字コード変換

UTF-8のままだとエクセルで文字化けするのでSJIS-winに文字コードを変換。

php://outputだとrewind()、fseek()が使えずファイルポインタを先頭に戻せないのでphp://tempを使用。


app/routes.php

<?php

// CSVダウンロード
Route::get('/csv', function() {
$users = \User::where('type', '=', '1')->get(['name', 'birth_day'])->toArray();
$stream = fopen('php://temp', 'r+b');
foreach ($users as $user) {
fputcsv($stream, $user);
}
rewind($stream);
$csv = str_replace(PHP_EOL, "\r\n", stream_get_contents($stream));
$csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8');
$headers = array(
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="users.csv"',
);
return Response::make($csv, 200, $headers);
});


【修正】ヘッダー行追加。


app/routes.php

<?php

// CSVダウンロード
Route::get('/csv', function() {
$users = \User::where('type', '=', '1')->get(['name', 'birth_day'])->toArray();
$csvHeader = ['名前', '誕生日'];
array_unshift($users, $csvHeader);
$stream = fopen('php://temp', 'r+b');
foreach ($users as $user) {
fputcsv($stream, $user);
}
rewind($stream);
$csv = str_replace(PHP_EOL, "\r\n", stream_get_contents($stream));
$csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8');
$headers = array(
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="users.csv"',
);
return Response::make($csv, 200, $headers);
});


【修正】ファサード対応


CSVクラス


app/Lib/CSV.php

<?php namespace MyProject\Lib\CSV;

use Response;

class CSV
{
public function __construct()
{
}

  /**
* 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);
}
$stream = fopen('php://temp', 'r+b');
foreach ($list as $row) {
fputcsv($stream, $row);
}
rewind($stream);
$csv = str_replace(PHP_EOL, "\r\n", stream_get_contents($stream));
$csv = mb_convert_encoding($csv, 'SJIS-win', 'UTF-8');
$headers = array(
'Content-Type' => 'text/csv',
'Content-Disposition' => "attachment; filename=$filename",
);
return \Response::make($csv, 200, $headers);
}
}



サービスプロバイダー


app/Lib/CSVServiceProvider.php

<?php namespace MyProject\Lib\CSV;

use Illuminate\Support\ServiceProvider;

class CSVServiceProvider extends ServiceProvider
{

public function register()
{
$this->app->bindshared('csv', function()
{
return new CSV;
});

}

}



ファサード


app/Facades/CSV.php

<?php namespace MyProject\Facades;

use Illuminate\Support\Facades\Facade;

class CSV extends Facade
{

public static function getFacadeAccessor()
{
return 'csv';
}

}



オートロード更新。

composer dump-autoload


パス追記


app/config/app.php

    'providers' => array(

   ……………………
'MyProject\CSV\CSVServiceProvider',// 追記

'aliases' => array(
   ……………………
'CSV' => 'MyProject\Facades\CSV',// 追記



コントローラー修正


app/routes.php

<?php

// CSVダウンロード
Route::get('/csv', function() {
$users = \User::where('type', '=', '1')->get(['name', 'birth_day'])->toArray();
$csvHeader = ['名前', '誕生日'];
return CSV::download($users, $csvHeader, 'user_list.csv');
});