ちょっと前にPHPでCSVインポートをする方法を書きまして。
今回はCSVエクスポート(ダウンロード)の方法をまるっとまとめたいと思います。
PHPでCSVエクスポートをするコード[laravel]
コントローラーのコードはこんな感じです。
public function export(Request $request)
{
$headers = [ //ヘッダー情報
'Content-type' => 'text/csv',
'Content-Disposition' => 'attachment; filename=csvexport.csv',
'Pragma' => 'no-cache',
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Expires' => '0',
];
$callback = function()
{
$createCsvFile = fopen('php://output', 'w'); //ファイル作成
$columns = [ //1行目の情報
'reserved_date',
'checkin_date',
'total_price',
];
mb_convert_variables('SJIS-win', 'UTF-8', $columns); //文字化け対策
fputcsv($createCsvFile, $columns); //1行目の情報を追記
$bookingCurve = DB::table('csvimport'); // データベースのテーブルを指定
$bookingCurveResults = $bookingCurve //データベースからデータ取得
->select(['reserved_date'
, 'checkin_date'
,DB::raw('sum(total_price) as total_price')])
->groupby('reserved_date')
->get();
foreach ($bookingCurveResults as $row) { //データを1行ずつ回す
$csv = [
$row->reserved_date, //オブジェクトなので -> で取得
$row->checkin_date,
$row->total_price,
];
mb_convert_variables('SJIS-win', 'UTF-8', $csv); //文字化け対策
fputcsv($createCsvFile, $csv); //ファイルに追記する
}
fclose($createCsvFile); //ファイル閉じる
};
return response()->stream($callback, 200, $headers); //ここで実行
}
大事な箇所を解説してみます。
PHPでCSVエクスポートの方法 ポイント1 response->stream
『laravel』でCSVエクスポートする方法をググっていたら、
こんなコメントを見つけたんですね。
参照記事:CSV export in laravel 5 controller
と取り入れつつ、いくつかググって実現できました。
return response()->stream($callback, 200, $headers);
streamの中に、
コールバック(関数、今回はCSVエクスポートする処理)と、
ヘッダ情報を指定しています。
まずはヘッダから。
PHPでCSVエクスポートの方法 ポイント2 HTTPヘッダ
インターネットを通じてやりとりする時は必ず、
『HTTP(エイチティーティーピー)』というルールにしたがう必要があります。
HTTP・・Hyper Text Transfer Protocol(ハイパーテキストトランスファープロトコル)
『プロトコル』というのが協定とか、決まりみたいな意味です。
で、
HTTPというルールでは必ず、『HTTPヘッダ』をつける決まりになってます。
このページがどんな種類で、どんな設定になってて・・
といった情報をまとめたのが、『HTTPヘッダ』になります。
今回の『HTTPヘッダ』はこんな感じです。
$headers = [
'Content-type' => 'text/csv', //CSV形式ですよー
'Content-Disposition' => 'attachment; filename=csvexport.csv', //添付ファイルありますよー、ファイル名は***.csvですよー
'Pragma' => 'no-cache', //キャッシュ(情報保存)しないですよー
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0', //キャッシュ期限切れなら確認してやー
'Expires' => '0', //キャッシュの有効期限は0ですよー
];
『キャッシュ』・・一度開いたWebページのデータを保存して、次回アクセス時にさくっと表示できる仕組み
『キャッシュ』を保存するようにすると、
次回アクセス時に読み込むスピードが早くなったりするメリットはあるんですが、
CSVエクスポートに関して言えば、キャッシュは保存しなくていいのかなと思います。
参考記事
『Webを支える技術』 第9章 HTTPヘッダ まとめメモ
次に、return response()->stream($callback, 200, $headers);
の中の、$callback の中で書かれている処理のポイントを。
PHPでCSVエクスポートの方法 ポイント3 お決まりの関数達
「PHP CSV エクスポート」でググるとかなりのサイトで
これらの関数が使われています。
fopen('php://output', 'w'); //ファイルを作成する 直接ブラウザに返す 書きこめる状態で
fputcsv($createCsvFile, $csv); //ファイルに追記する
fclose($createCsvFile); //ファイルを閉じる
ファイル開いて、
データ追記して、
ファイル閉じて。
PHPでCSVエクスポートの方法 ポイント4 文字化け対策
文字化けに関しては、
WindowsとMacで設定が違うんですが、今回はWindowsを対象に。
WindowsでCSVを開く時はエクセルを使うことが多く、
エクセルは文字コードが『SJIS(エスジス)』になっているので、『SJIS』に合わせないと文字化けしてしまいます。
PHPでは mb_convert_variables という関数を使って文字コードを変更できるので、
1行ずつ文字コードを『UTF-8』から『SJIS』に変更するようにしています。
mb_convert_variables('SJIS-win', 'UTF-8', $columns); //文字化け対策
mb_convert_variables('SJIS-win', 'UTF-8', $csv); //文字化け対策
PHPでCSVエクスポートの方法 ポイント5 forechで繰り返す
データベースからデータを取得して、
foreachで1行ずつCSVファイルに追記していきます。
100行なら100回。
1000行なら1000回繰り返します。
foreach ($bookingCurveResults as $row) {
$csv = [
$row->reserved_date,
$row->checkin_date,
$row->total_price,
];
データベースのデータをとってくる際は『オブジェクト型』になっているので -> で指定する必要あります。
参考記事
これらを踏まえてもう一回コードを。
public function export(Request $request)
{
$headers = [ //ヘッダー情報
'Content-type' => 'text/csv',
'Content-Disposition' => 'attachment; filename=csvexport.csv',
'Pragma' => 'no-cache',
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
'Expires' => '0',
];
$callback = function()
{
$createCsvFile = fopen('php://output', 'w'); //ファイル作成
$columns = [ //1行目の情報
'reserved_date',
'checkin_date',
'total_price',
];
mb_convert_variables('SJIS-win', 'UTF-8', $columns); //文字化け対策
fputcsv($createCsvFile, $columns); //1行目の情報を追記
$bookingCurve = DB::table('csvimport'); // データベースのテーブルを指定
$bookingCurveResults = $bookingCurve //データベースからデータ取得
->select(['reserved_date'
, 'checkin_date'
,DB::raw('sum(total_price) as total_price')])
->groupby('reserved_date')
->get();
foreach ($bookingCurveResults as $row) { //データを1行ずつ回す
$csv = [
$row->reserved_date, //オブジェクトなので -> で取得
$row->checkin_date,
$row->total_price,
];
mb_convert_variables('SJIS-win', 'UTF-8', $csv); //文字化け対策
fputcsv($createCsvFile, $csv); //ファイルに追記する
}
fclose($createCsvFile); //ファイル閉じる
};
return response()->stream($callback, 200, $headers); //ここで実行
}
さいごに
仕事で使うWEBサイトやWEBページでは、
必ずと言っていいほど『CSVエクスポート(ダウンロード)』の要望があります。
的な。
そんな時のために、
- responseとstream
- ヘッダ情報追加する
- よく使う関数(fopen, fputcsv, fclose)を知っておく
- 文字化け対策
- foreachで回す
といった流れをざっくりでも把握しておくと、いざって時にさくっと作れるかもですね。
参考記事
laravel5.3 CSVダウンロードを実装する(あしたからがんばるさん)
Laravel5.4で、CSVダウンロード(一言多いプログラマーの独り言)
追記 2019/1/22
Laravel5.5にアップデート後 実行したらなぜかエラー。
いくつかぐぐると、config/database.php 内の strict が true になっていることが原因のようで、
falseに変更するとOKになりました。
いずれ原因解明したいところです。
QueryBuilderでgroupByをするとSyntax error or access violationがでる件
『PHP(Laravel)』ではこんな記事も読まれています。
1. 【PHP/Laravel】初心者向けの動画をリリースしました【Udemy】2. 【Laravel(PHP)】初心者向け アプリのつくり方 をリリースしました【techpit】
3. 【PHP】【Laravel】CSVエクスポートの方法〜5つのポイント〜
4. 【PHP】オブジェクトと連想配列の違いについて調べてみた【初心者向け】
5. 【PHP】CSVインポートの方法〜大量データもバルクインサートでバッチリ!〜【laravel】
6. 【PHP】【図解】クラスと抽象クラスとインターフェースとトレイトとDIをまとめてみた【初心者向け】
7. 【PHP】配列や連想配列が覚えづらかったので学校に例えてみた【初心者向け】
8. 【PHP】ホームページに天気予報を表示させる方法【Webスクレイピング】【初心者向け】
9. 【Laravel】Webアプリ環境構築の仕方【Vue.js】【初心者向け】
10. 【PHP】2次元(多次元)配列でデータ取得したいならarray_columnがめっさ便利
アオキのツイッターアカウント。















この記事へのコメントはありません。