web制作会社で働いていると、
「このデータをcsvファイルで欲しい!」
「ブラウザから簡単に、データをcsvでダウンロードできるようにしてほしい!」
といった要望が多々あったりします。
DBからデータを取り出してcsvファイル化する、と聞くと一見難しいように聞こえますが
PHPにはファイル出力用の関数が用意されているので、思ったよりカンタンに実装できちゃうんです!
それでは早速みていきましょう!
目次
1.ダウンロード用のボタンを作成
actionの遷移先にdownload.phpを設定し、ボタンを作成します。
1 2 3 4 5 6 | <form id="form1" class="form_wrap" action="./download.php" method="POST"> <div class="csv_import_textarea"> <input type="hidden" name="key" value="runrunrun"> <input type="submit" value="csvダウンロード"> <div> </form> |
2.download.phpを作成・記述
download.phpを作成し、以下を記述していきましょう!
ファイルを開いて準備
まず、$filenameにファイル名を格納します。
1 2 | //ファイル名 $filename = 'test_user.csv'; |
ファイルを開きます。
fopen()とはファイルをオープンしてくれる関数で、引数に「開きたいファイル名」と「ファイルを開くときのモード」を指定します。
以下と書くことで、「$filenameを書き込みモードで開く(write)」となります。
1 2 3 4 | if (!$fp = fopen($filename, 'w')) { echo "Cannot open file ($filename)"; exit; } |
次に、ファイルに項目を書き込んでいきましょう。
$headに項目を格納します。
mb_convert_encoding関数で文字コードを変換した$headを、fwrite関数でファイルに書き込むことができます。
1 2 3 4 | $head = 'id,email,created'; // head書き込み fwrite($fp, mb_convert_encoding($head . "\n", "SJIS")); |
ちなみになぜ、文字コードを「SJIS」で出力するのでしょうか?
それは、PHPでの標準文字コードはUTF-8ですが、Excelでは文字コードShift-JISが使われているので、UTF-8からShift-JISに変換しないとExcelで開いたときに文字化けしてしまうからです。
せっかくダウンロードできても読めないと、がっかりですよね。
DBのデータをファイルに書き込む
いよいよDBに接続し、DBからデータをとってきてfwrite関数で書き込んでいきます!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 | try{ $pdo = db_connect(); $sql = 'SELECT * FROM t_user'; $sql = $pdo->prepare($sql); $sql->execute(); while($data = $sql->fetch()){ // 出力用 $output_text = '"'; $output_text .= $data['id']; $output_text .= '","' . $data['email']; $output_text .= '","' . $data['created']; $output_text .= '"'; $output_text .= "\n"; if (fwrite($fp, mb_convert_encoding($output_text, "SJIS")) === FALSE) { break; } } // close mysql $pdo = null; } catch (PDOException $e) { print "[ERROR] {{$e->getMessage()}}\n"; die(); } // close mysql $pdo = null; } catch (PDOException $e) { print "[ERROR] {{$e->getMessage()}}\n"; die(); } |
テーブルを選択し、$dataに格納した配列をwhile文でループさせます。fetch()と書くことで一つずつ値をとることができ、データがなくなったらループを抜けるという処理になっています。
これで、DBのデータをファイルに書き込むことができました!
fclose関数でファイルを閉じましょう。
1 | fclose($fp); |
ダウンロードする関数を用意・実行
最後にダウンロードする関数を用意して、実行で完了です。
ファイルが存在するか、オープンできるか、ファイルサイズは大丈夫かをチェックし、関数の中でダウンロード用のHTTPヘッダーを設定し、ファイルを出力しています。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | /* download_file関数実行 */ download_file($filename); function download_file($path_file) { /* ファイルの存在確認 */ if (!file_exists($path_file)) { die("Error: File(".$path_file.") does not exist"); } /* オープンできるか確認 */ if (!($fp = fopen($path_file, "r"))) { die("Error: Cannot open the file(".$path_file.")"); } fclose($fp); /* ファイルサイズの確認 */ if (($content_length = filesize($path_file)) == 0) { die("Error: File size is 0.(".$path_file.")"); } /* ダウンロード用のHTTPヘッダー送信 */ header("Cache-Control: private"); header("Pragma: private"); header('Content-Description: File Transfer'); header("Content-Disposition: inline; filename=\"".basename($path_file)."\""); header("Content-Length: ".$content_length); header("Content-Type: application/octet-stream"); header('Content-Transfer-Encoding: binary'); /* ファイルを読んで出力 */ if (!readfile($path_file)) { die("Cannot read the file(".$path_file.")"); } } |
HTTPヘッダーについて
HTTPヘッダーとは、ブラウザからサーバーに出されるHTTPリクエストの一部分のことです。
ブラウザ上では https://b-risk.jp といったurlを叩いて、サイトが見れますよね。なぜ見れるかというと、HTTP通信というのが行われているからです。
このHTTP通信を構成するのが「HTTPリクエスト」と「HTTPレスポンス」というものです。
「HTTPリクエスト」はブラウザからサーバーに送られるリクエストで、「HTTPレスポンス」はそれに応えて、サーバーからブラウザに送られるレスポンスのことです。
この「HTTPリクエスト」を構成するうちの一つが、ここで出てきた「HTTPヘッダー」なのです。
今回の目的はブラウザからcsvファイルをダウンロードしたいということなので、ブラウザからサーバーへのリクエストにcsvファイルの情報を付与してあげる必要があります。
その処理をheader関数を使って書いているというわけです。
ダウンロード用のHTTPヘッダー送信
CSVファイルをダウンロードするには、ダウンロード用のHTTPヘッダーを設定する必要があります。
header関数で、以下の情報をHTTPヘッダーに設定することができます。
- ファイルのタイプ
- ファイルのサイズ
- ファイルの処理方法
csvをダウンロードするためには「Content-Type(ファイルタイプ)」に「application/octet-stream」を指定してあげます。これはファイルタイプを特に意識する必要のないときに使う形式です。
また、「Content-Length(ファイルのサイズ)」を指定することで、ダウンロードの進捗状況を表示させることができ、「Content-Description(ファイルの処理方法)」に「ファイル名」を指定することで、保存する際、ブラウザにそのファイル名でダイアログが表示されます。
ファイル生成!
これで、最初に用意したダウンロード用ボタンをクリックすると、以下のようなcsvファイルが生成されダウンロードできるかと思います!
項目は id,email, createdで、DBからとってきたデータもちゃんと表示されています。
サーバーの細かな部分もありましたが、要はファイルを開いて書き込んで、閉じてダウンロードさせる!という流れをコードで書けばOK!ということですね!
関数が用意されているので、直感的にできる部分も多くあったのではと思います。
まとめ
今回はcsvダウンロードでも、比較的簡単なものをご紹介しました!
案件の中には、膨大なユーザ―データや都道府県、建物などを出力するような、複雑なケースも多いと思います。
今回のサンプルのようにシンプルなデータの持ち方で、csvダウンロードの流れや、プログラムがどう動いてるかをしっかり理解できるようになると、上記のような規模の大きい案件にも太刀打ちできるのではないかと思います!
こなせる仕事の幅もグッと広がると思うので、是非自分のものにしていってください。