質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

Q&A

4回答

3053閲覧

Laravelでcsvファイルをダウンロードできるようにする

tanukitii

総合スコア44

Laravel

LaravelとはTaylor Otwellによって開発された、オープンソースなPHPフレームワークです。Laravelはシンプルで表現的なシンタックスを持ち合わせており、ウェブアプリケーション開発の手助けをしてくれます。

0グッド

0クリップ

投稿2019/06/26 11:53

編集2019/06/27 14:43

追記:
hentaimanさんからご教示いただいたURLから,csvファイルを取得するためのツールをダウンロードし,使ってみたところ,私がやりたいことが実現できました。
ただ,現在,多くの方がこれ以外で,別の解決策を提示してくださっているので,それらも検証してみようかと思います。その結果次第で,ベストアンサーを決めようかと思います。
お待たせしてしまうかもしれませんが,しばらくお待ちくださいますようよろしくお願いいたします。


質問

途中までコードを書いていて,いろいろ試した結果何をどうすればよいのか分からなくなってしまいました。
下記に,コードの一部をまとめますので,どうしたらcsvファイルをダウンロードできるようになるかご教示いただけると幸いです。

web

1Route::get('users/csv', 'csvController@download'); // <-これ 2Route::resource('users', 'UserController');

csvController

1 2class csvController extends Controller 3{ 4 //2つのテーブル(tbl_userとtbl_way)を結合し,tbl_userのidとname,tbl_wayのway_nameを 5  //csvファイルで取得する。 6 public function download( Request $request ) 7 { 8 //テーブルの結合 9 $users = DB::table('tbl_users') 10 ->leftJoin('tbl_ways', 'tbl_users.way_id', '=', 'tbl_ways.id') 11 ->get(); 12 13 $response = new StreamedResponse (function() use ($request){ 14   15       //ファイルを開く 16 $stream = fopen('php://output', 'w'); 17 18 // 文字化け回避 19 stream_filter_prepend($stream,'convert.iconv.utf-8/cp932//TRANSLIT'); 20 21 // タイトルを追加 22 fputcsv($stream, ['id', '氏名', '移動手段']); 23 24 foreach ($users as $user) { 25 fputcsv($stream, [$user->id, $user->name, $user->way_name]); 26 }; 27 28       //ファイルを閉じる 29 fclose($stream); 30 }); 31 32     //ここから下のコードについては何かよくわかっていない。 33 //特に何をreturnすればよいか分からない。 34 $response->headers->set('Content-Type', 'application/octet-stream'); 35 $response->headers->set('Content-Disposition', 36                  'attachment; filename="ファイル名.csv"'); 37 return view('users/index'); 38 } 39} 40

index.blade.phpでボタンを設置し,クリックした際にcsvファイルがダウンロードできるようにします。
そのとき,現在いるぺージからは遷移しないようにする予定でした。

index

1<form action="users/csv" method="get"> 2 <input type="submit" value="csv"> 3</form>

補足説明

テーブルは下記の2つ。tbl_wayがtbl_userのマスターテーブルで,idとway_idが紐づいています。
tbl_user

idnameway_id
1taro1
2yamada2
3ziro1

tbl_way

idway_name
1train
2walk

なお,csvファイルでダウンロードした際,下記のような結果を期待しております。

id氏名移動手段
1tarotrain
2yamadawalk
3zirotrain

以上です。
もし,どなたか分かれば,ご教示いただけると幸いです。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答4

0

csvの話だけなら、他の人が書いてあるようにライブラリを使えばいいと思うんですが、それだと質問の趣旨と変わってしまいそうなので・・・

ここから下のコードについては何かよくわかっていない。

$response->headers->set('Content-Type', 'application/octet-stream');

レスポンスヘッダに、コンテンツタイプがダウンロードコンテンツ(application/octet-stream)ということをを設定します。
csvなら text/csv でもよいかと思います。

$response->headers->set('Content-Disposition',                   'attachment; filename="ファイル名.csv"');

レスポンスヘッダに、Content-Dispositionを設定します。
書いてある通りファイル名をセットします。

特に何をreturnすればよいか分からない。

$responseをリターンしてください。


HTTPレスポンスにはheaderとbodyがあるのですが
HTML等が入っっている部分がbody、どこのサーバが返した、コンテンツのタイプなどを管理しているのが、headerです。

headerとbodyをまとめて管理しているのが、Responseで、その中でもストリーム処理ができるresponseクラスがStreamedResponseという感じです。

投稿2019/06/27 09:03

mikkame

総合スコア5036

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikkame

2019/06/27 09:13

あとコールバック用の関数のuseにusersがないので実行時に落ちる気がします。 use($request, $users)にすればこと無きを得る気がしますが 詳細は`無名関数`とか、`即時関数`で調べてみてください。
tanukitii

2019/06/27 14:48

ご回答いただき,誠にありがとうございます。 >HTTPレスポンスにはheaderとbodyがあるのですが 久々にそのワードを聞きました。昔ちらっと触れたきりだったので,忘れてしまっていました。 これを機に復習してみようかと思います。 また,後ほど,mikkameさんからご教示いただいたことを検証してみようかと思います。
tanukitii

2019/07/02 06:49 編集

検証するための時間がとれなくて,ご連絡が遅くなってしまいました。 申し訳ございません。 return $response;も試してみたところ,下記URLのぺージに遷移するのですが, localhost:8000/users/csv? 「このサイトにアクセスできません」と表示されます。 returnに渡すものも原因かと思いますが,それ以外でも何か原因があるかもしれません。 もし,心当たりがあれば,ご教示いただけると幸いです。 宜しくお願いいたします。
guest

0

//特に何をreturnすればよいか分からない。

return;で良いと思います。
レスポンスヘッダにapplication/octet-streamを指定した時点でブラウザへの画面出力は発生しないわけなので。
実際にPure PHPでダウンロード処理を作るときもreadfile(ファイルパス);したあとにexit;で終わることもあります。

投稿2019/06/27 00:47

m.ts10806

総合スコア80850

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikkame

2019/06/27 09:04

> レスポンスヘッダにapplication/octet-streamを指定した時点でブラウザへの画面出力は発生しないわけなので。 これなんですが、レスポンスインスタンスに設定しているだけなので、 そのレスポンスインスタンスを返さないと、インスタンスを作成して設定しただけ、となってしまう気がします (もちろん、通常のheader関数などで処理すればご指摘の通りです)
tanukitii

2019/06/27 14:53

ご回答いただき,誠にありがとうございます。 お二人からご助言いただいたことをコードに反映させ,検証してみようかと思います。 用語については,私自身まだ理解できていないものもあったので,それについても調べてみようかと思います。
tanukitii

2019/07/02 06:42

ご連絡が遅くなってしまい,申し訳ないです。 なかなか時間がとれず,検証に時間がかかってしまいました。 結論から申し上げますと,return;だと真っ白な下記URLのぺージに遷移するだけで,ダウンロードもされないといった感じになります。 http://localhost:8000/users/csv? returnに渡すものが何かではなく,ルーティングの設定が間違っているなど,他の理由は考えられないでしょうか。申し訳ございません。よろしくお願いいたします。
m.ts10806

2019/07/02 06:49

と思ったらmikkameさんの回答にありましたね。
tanukitii

2019/07/02 09:48

はい。 で,それも試してみたのですが,問題を解消できないという状況です。 他に理由があるのでしょうね…(私の勉強不足でしょうね…)
m.ts10806

2019/07/02 10:05

回答者の意図通りに組めているかまでは分からないので現在のコードと起きている現象を質問に追記してください(流れもあるので更新ではなく追記でお願いします)
guest

0

実際に使ってるのはこの辺だけど自分で試して選ぶしかない。
https://github.com/thephpleague/csv
https://github.com/Maatwebsite/Laravel-Excel

Laravel用はしばらく使ってみないと分からないことも多い。
composerでこんな指定してるとバージョンアップ時にすぐ対応してくれるかどうかが重要。

"illuminate/support": "5.5.*|5.6.*|5.7.*|5.8.*",
"illuminate/support": "5.3.* || 5.4.* || 5.5.* || 5.6.* || 5.7.* || 5.8.*",

5.9出てもこのままだとインストールできないので対応待ちの時間ができる。
^5.5で指定してくれればいいのに。
バージョンアップへの対応がないとか遅いせいで使わなくなったパッケージが大量にある。

投稿2019/06/26 13:07

kawax

総合スコア10377

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanukitii

2019/06/26 13:21

早速のご回答誠にありがとうございます。 自分実装は勉強のためにとどめておき,実際に何かアプリケーションを作る際は, できるだけ,すでに用意されているものを使用するというのが一般的なんですね。 いろいろ試してみようかと思います。 ちなみに私が使用しているLaravelのバージョンは5.8.23です。
guest

0

特に自前でコードを書くことに拘らないのならテキトーなもの追加して使うといいですよ。
検索したらパッと二つヒットすると思うけど、特に簡単で使いやすかった方紹介します。
fast-excel
名前にはエクセルって書いてあるけどcsvも出せます

投稿2019/06/26 12:25

hentaiman

総合スコア6421

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tanukitii

2019/06/26 13:18

早速のご回答誠にありがとうございます。 私は,情報系出の人間ではないので,書籍やqiitaで勉強してましたが, GitHubなどですでに用意されているものを使用するというのが一般的なんですね。 GitHubで何かを使ってみようという機会はなかったのですが,これを機に使ってみようと思います。
hentaiman

2019/06/26 13:22

今回の場合githubは特に関係無いですが、githubにインストールから使い方までを公開されてるのでURLを載せておきました。 実際に使う時はgitのコマンドは使いません。githubに書いてあるようにcomposerを使ってインストールしてから使う事になります。
tanukitii

2019/06/26 17:59

確かに仰る通りかと思います。composerはインストールしているので,説明を読みながら使用してみようと思います。 この度は,私の質問に対し,多くのことをご教示いただき,誠にありがとうございます。
tanukitii

2019/06/26 19:50

度々,申し訳ございません。 教えていただいたサイトを参考に,実行してみたのですが,うまくいかず困っています。 web.php Route::get('users/csv', 'csvController@downloadCSV'); index.blade.php <form action="users/csv" method="get"> <input type="submit" value="csv"> </form> csvController.php class csvController extends Controller { public function downloadCSV (Request $request) { // Load users $users = tbl_user::all(); dd($users); // Export all users (new FastExcel($users))->export('file.xlsx'); } } と書いたのですが,真っ白なページに遷移しただけで,何も実行されません。index.blade.phpからの呼び出し方が悪いのでしょうか。 お手数をおかけいたしますが,よろしくお願いいたします。
hentaiman

2019/06/26 20:01

ルーティングとかは分かってると思うので、そこ以外についての返事します。 export使ってるからファイルとして書き出されてると思います、白くなるのはreturnが無いからです。 やりたい事はダウンロードですよね、exportしないでも直接DL出来るメソッド(download)があるのでそれを使うといいです。 githubのexportのサンプルのちょっと下にサンプルコード書いてあります。
tanukitii

2019/06/27 14:27

あ,できました! Controllerにdownloadメソッドを記述し,web.phpに Route::get('users/csv', 'csvController@downloadCSV'); を追加することで,現在いるぺージから移動することなくcsvファイルをダウンロードできました。 ただ,web.phpのgetで,users/csvとしているのにURLが変化しない理由がまだわかっていないので, コードを見てみようと思います。
hentaiman

2019/06/27 15:38

URLが変化しないの理由ってのは、ダウンロードボタン(?)を押したのにブラウザのアドレスバーが変わらないのにCSVダウンロード出来てしまうのは何で?って意味ですか? もしそういういう意味で言ってるならそれが普通の動作です。そこら辺のサイトでzipとかDLする時にアドレスバーにはzipとか表示されないのと同じことです。 そういう意味じゃないんなら、ちょっと何言ってるか分かんないな・・・
tanukitii

2019/06/29 03:59

現在いるページがlocalhost:8000/usersで,ダウンロードボタンをクリックすると, web.phpのRoute::get('users/csv', 'csvController@downloadCSV'); が呼び出されるので,URLがlocalhost:8000/users/csvに変わってしまうのではないかと思っていたのですが,ボタンをクリックしても,localhost:8000/usersのままなので,どうしてだろう? という意味でした。分かりにくくて申し訳ないです。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問