☆Yuus Memo☆
非エンジニアの方でも業務を効率化できるプログラムを紹介します!
Laravel

【Laravel】CSVエクスポート ☆超簡単!!

皆さんこんにちは!!
今日は、PHPのフレームワークのLaravelでCSVエクスポートを行う方法を解説したいと思います。

CSVのエクスポート機能は、業務システムでは必須の機能ですし、WEBサイトの管理などでもアクセス数などの詳細データを出力したりするなど、必要となるケースは非常に多いです。

CSVとは

comma-separated values(略称:CSV)は、テキストデータをいくつかのフィールド(項目)に分け、区切り文字であるカンマ「,」で区切ったデータ形式。拡張子は .csv、MIMEタイプは text/csv。
「comma-separated variables」とも言う。日本語では広く普及した訳語はないが、「カンマ区切り」「コンマ区切り」などとも呼ばれる。Microsoft Excelの日本語版では「CSV (カンマ区切り)」としている。

出典: フリー百科事典『ウィキペディア(Wikipedia)』

例えば以下のようなデータのことです。

氏名,年代,性別,住所
山田 花子,30代,女性,東京都豊島区
田中 太郎,50代,男性,和歌山県有田郡

1単語ずつカンマで区切られていて、1行ずつ情報が並んでいます。また、テキストデータとは文字のみのデータのことを指し、ワードやエクセルのように画像が入っていたり、文字サイズや色の装飾などがされていないプレーンな文字データのことを言います。
通常のテキストデータの拡張子は「.txt」ですがCSVの場合は「.csv」となります。

CSVを使用するメリット

システムやサービス独自のデータ形式で扱われている場合、似たサービスへ移行をしたくても互換性がなくデータが移行できません。そんなとき、各ソフトウェアが共通で対応している形式でエクスポートおよびインポート(ダウンロードやアップロードみたいなこと)ができれば簡単にデータの移行が可能になります。その共通で対応している形式としてよく使われるのがCSVファイル形式なのです。

そしてCSVファイルであれば専用のソフトウェアがなくてもメモ帳やエクセルなどで編集できるのもメリットの1つです。

LaravelでCSV出力

それでは、サクッとコードを書いていきたいと思います。

今回の記事はLaravelのプロジェクトの作成や、View・Modelなど基本的なものは出来上がっているものとして、「CSVを出力する」ということに絞って書いています。

実用例が欲しい場合、コメント下さい。

今回はLaravelのStreamedResponseファザードを使って、ダウンロードダイアログを出す方法でCSVエクスポートを実装していきます。

CSVエクスポートには大きく分けて、以下2つの作業が必要になります。

  • CSVファイルに必要なデータを用意する
  • リクエストを出したユーザーにCSVファイルをダウンロードさせる

「CSVファイルに必要なデータを用意する」部分は、findメソッドやSQLで連想配列を用意していただければ良いので、今回は解説を省きます。

まず、コントローラーの先頭に下記のuse分を追加して下さい。

use Symfony\Component\HttpFoundation\StreamedResponse;

そして、下記の関数をコントローラに記述して下さい。

public function csvExport(Request $request) {
        $post = $request->all(); // 本来ならここで、CSV出力のパラメータを受け取り、クエリで絞り込む
        $response = new StreamedResponse(function () use ($request, $post) {
            $stream = fopen('php://output','w');
            // 文字化け回避
            stream_filter_prepend($stream, 'convert.iconv.utf-8/cp932//TRANSLIT');

            // ここでは仮に「products」というテーブルの全データを取得
            $results = Product::all();
            if (empty($results[0])) {
                    fputcsv($stream, [
                        'データが存在しませんでした。',
                    ]);
            } else {
                foreach ($results as $row) {
                    fputcsv($stream, $this->_csvRow($row));
                }
            }
            fclose($stream);
        });
        $response->headers->set('Content-Type', 'application/octet-stream'); 
        $response->headers->set('content-disposition', 'attachment; filename=商品一覧.csv');

        return $response;
    }
}

/*
* CSVの1行分のデータ ※本来はコントローラに書かない方が良い
*/
private function _csvRow($row){
        return [
            $row->id,
            $row->product_cd,
            $row->product_name,
            $row->unit,
            $row->cost,
            $row->price,
            $row->memo,
        ];
    }

基本的には上記のようなコードになります。

コードの解説

あんまり解説が必要な部分も無いのですが、ちょっとしたポイントだけ書いておきます。

fopen

fopenはファイルまたはURLをブラウザで開くPHPの関数です。

fopenの引数に作成したCSVファイルを入れることでダウンロードを実現しています。

$stream = fopen('php://output','w');

日本語文字化け対策

stream_filter_prepend の引数に convert.iconv.utf-8/cp932//TRANSLIT を入れることで、UTF-8へ文字列を変換してマルチバイト文字が入っていても文字化けがでないように対策しています。

stream_filter_prepend($stream, 'convert.iconv.utf-8/cp932//TRANSLIT');

fputcsv

fputcsvはその名の通り、データをCSVとして書き込む関数です。データは配列にして渡す必要があります。
1行分の配列は「_csvRow」で取り出しています。

    // ここでは仮に「products」というテーブルの全データを取得
    $results = Product::all();
    if (empty($results[0])) {
            fputcsv($stream, [
                'データが存在しませんでした。',
            ]);
    } else {
        foreach ($results as $row) {
            fputcsv($stream, $this->_csvRow($row));
        }
    }
    fclose($stream);

出力データが無い場合、データが存在しないということをユーザーへ伝える処理も入れています。

レスポンスヘッダー

レスポンスヘッダーはhttpリクエストに対する返答に付与する追加情報です。

レスポンスヘッダーにContent-Typeとファイル名を指定するとCSVファイルとしてダウンロードできます。

また、ユーザーが指定した期間をファイル名に変数で入力することによって、管理しやすくなるように工夫しています。

$response->headers->set('Content-Type', 'application/octet-stream'); 
$response->headers->set('content-disposition', 'attachment; filename=商品一覧.csv');

あとは「csvExport」アクションを呼び出すルートを記述し、View側にルートに紐づいたフォームを用意してやれば良いですね!!

まとめ

いかがでしたか?
CSV出力は、WEBシステムに限らず色々な場面で必要になります。
その分、色々なやり方があり、混乱するかもしれませんが、基本的にはこの記事で紹介したように、とてもシンプルなやり方で実装できます。

LaravelでのCSV出力を紹介しましたが、PHPの他のフレームワークでもやることは殆ど変わりませんので、今回のコードをよく覚えて下さい!!


コメントを残す