プログラミング

PHPでCSVをダウンロードする方法

hebishima.shogo

はい、hebiです。

画面に表示している一覧をCSVファイルでダウンロードしたいと要望がありましたので、CSVファイルのダウンロード方法を記事にしたいと思います。

スポンサーリンク

前提

以下の記事で作成した環境で説明していきます。

あわせて読みたい
Amazon LinuxにPHPとApacheをインストールする方法
Amazon LinuxにPHPとApacheをインストールする方法
あわせて読みたい
【PHP】CodeIgniter4のインストール方法
【PHP】CodeIgniter4のインストール方法

CSVとは

CSV(Comma-Separated Values)は、テキスト形式のファイルフォーマットの一つです。
データをカンマやタブ区切りの表形式で記述します。

以下はカンマ区切りで作成したCSVファイルの例です。

カンマ区切りCSVファイル
name,sex
ぺんぎん,1
hebi,2

「name,sex」がフィールド名です。
nameの列にぺんぎんhebiのデータがあります。
sexの列に1(男性)2(女性)のデータがあります。

このようなCSVファイルはExcelやスプレッドシートで開いて、データの解析や集計に使ったりします。

CSVダウンロード処理

では、CSVダウンロード処理を実装していきましょう!
画面に配置したボタンをクリックしたらCSVファイルがダウンロードされるように実装していきます。

ダウンロードAPIを作成

コントローラにダウンロードAPIを作成します。

public function download()
{
    // ファイル名を定義します
    $filename = 'download.csv';
    
    // CSVファイルに出力するデータ
	$data = array(
        array(
            'name' => 'ぺんぎn',
            'sex' => '1',
        ),
        array(
            'name' => 'hebi',
            'sex' => '2',
        ),
    );

    // レスポンスを設定してファイルをダウンロードします
    $response = $this->response
        ->setContentType('text/csv')
        ->setHeader('Content-Disposition', 'attachment; filename="' . $filename . '"')
        ->setBody($this->array_to_csv($data));

    return $response;
}

CSVファイルに出力するデータはハードコードとしてますが、DBからデータを取得した場合にも、$dataに定義したような配列データが取得されます。

ポイント

レスポンスに設定する内容は以下のとおりです。

  • setContentType(‘text/csv’)
    CSVファイルとして設定します。
  • Content-Dispositionヘッダー
    Content-Dispositionを指定すると、ブラウザにダウンロード方法や表示方法を指示することができます。
  • attachment
    attachmentを指定するとブラウザにダウンロードを指示します。
    ※inlineを指定するとブラウザ上に表示するように指示できます。
  • filenameにはダウンロードするファイル名を指定します。
  • Bodyにはダウンロードするファイル自体を指定します。
  • 自作したarray_to_csv関数でCSVデータをCSVファイルへ変換してBodyに設定してます。(STEP2で説明。)
CSVデータをCSVファイルへ変換

CSVデータとして作成したただの配列データを、CSVファイルへ変換する関数を作成します。外部公開は行わないためprivateにしてます。

private function array_to_csv(array $array)
{
    if (count($array) == 0) {
        return null;
    }

    // keyをヘッダーとして抽出
    $headers = array_keys($array[0]);

    ob_start();
    $df = fopen("php://output", 'w');

    // BOM を追加(Excelでの文字化けを回避)
    fwrite($df, "\xEF\xBB\xBF");

    // ヘッダーを出力
    fputcsv($df, $headers);

    foreach ($array as $row) {
        
        // バリューの値を変更したい場合は以下のように実装
        $record = [];
        foreach ($row as $key => $value) {
            if ($key === 'sex') {
                if ($value == 1) {
                	// sexが1の場合は男を設定
                    $record[] = '男';
                }else{
                	// sexが1以外の場合は女を設定
                	$record[] = '女';
                }
            } else {
                $record[] = $value; // その他の場合はそのまま追加
            }
        }
        // データをCSVファイルに書き込む
        fputcsv($df, $record);
        
        // 特に値の変更不要な場合はforeachの処理は不要で$rowをそのまま書き込む
        // fputcsv($df, $row);
    }
    fclose($df);
    return ob_get_clean();
}
ポイント
  • ob_start()
    関数は、出力バッファリングを開始します。これにより、すべての出力が一時的にバッファに保存されます。
  • $df =fopen(“php://output”, ‘w’)
    書き込みを行うためのファイルポインタをオープンします。ここでは、”php://output” を指定していますが、これはPHPの標準出力ストリームへの参照です。$dfがファイルポインタとなり$dfに対して書き込みを行うことができます。
  • fputcsv($df, $headers)、fputcsv($df, $record)
    指定したファイルポインタにCSV形式でデータを書き込みます。
    先にフィールド($headers)を書き込み、ループ処理でデータを書き込んでます。
  • fclose($df)
    書き込みが終わったので、ファイルポインタを閉じます。
  • ob_get_clean()
    出力バッファを取得してクリアします。つまり、これによりバッファに溜まった内容が文字列として取得され、同時にバッファはクリアされます。
ルーティング設定

フロントからdownloadを実行できるようにルーティング設定します。

$routes->get('/download', 'Home::download');

以上でサーバー側の実装は完了です。

ダウンロードAPIを実行するボタンを配置

フロント側の実装として、downloadを実行するボタンを作成します。

<button class="btn btn-info" onclick="window.location.href='http://xxxxxx/download'">ダウンロード</button>

お疲れ様でした。以上で全ての実装が完了です!

ダウンロード確認

ダウンロードボタンをクリックし、ダウンロードされることを確認しましょう。

ダウンロードできましたね!
ファイルの中身も想定どおりです!

最後に

CSVファイルをダウンロードできましたでしょうか?

CSVをダウンロードしたいという要望は多くあると思いますので、ぜひ参考にしてみてください!

逆にアップロードしたい。という要望もあると思いますので、どこかで記事にしたいと思います!(CSVファイルに限らず、ファイルのアップロード。)

最後までお読みいただきありがとうございました(^^♪

スポンサーリンク
ABOUT ME
hebi
hebi
エンジニア
フルスタックエンジニアとして活躍中。
HTML5プロフェッショナル認定Level1、Level2所持者です。

未経験の方でも簡単にプログラミングを学べるようにと情報を発信しております。
記事URLをコピーしました