ちょっと前に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がめっさ便利
アオキのツイッターアカウント。
この記事へのコメントはありません。