2012年3月12日月曜日

[PHP] 配列からCSVを作成しダウンロード

DBなどからデータを引き出し、CSV形式でダウンロードさせることは往々にしてある。
ロジック自体はそこまで複雑じゃないので毎回書いてもいいが、
数が多いと面倒なので関数にしてしまう。

//link・・・http://mio-koduki.blogspot.com/2012/03/php-csv.html
//第一引数・・・ダウンロードするときのファイル名
//第二引数・・・CSVにする配列(array(array(data1,data2),array(data1,data2))の2次元配列形式)
//第三引数・・・ヘッダを付ける場合は配列を渡す(array(header1,header2)の配列形式)
//返り値・・・なし
function csv_download($file_name,$data,$header=null)
{
    //ヘッダを付ける場合はarray(header1,header2)の形式で渡す
    if($header!=null)
    {
        array_unshift($data,$header);
    }

    //PHPのテンポラリに読み書きの準備をする
    $fp=fopen('php://temp','r+');
    foreach($data as $v)
    {
        //テンポラリにCSV形式で書き込む
        fputcsv($fp,$v,',','"');
    }
    //ファイルポインタを一番先頭に戻す
    rewind($fp);
    //ファイルポインタの今の位置から全てを読み込み文字列へ代入
    $csv=stream_get_contents($fp);
    //SJISに変える
    $csv=mb_convert_encoding($csv,'SJIS',mb_internal_encoding());
    //ファイルポインタを閉じる
    fclose($fp);
    //渡されたファイル名の拡張子やパスを切り落とす
    $file_name=basename($file_name);

    //ダウンロードヘッダ定義
    header('Content-Disposition:attachment; filename="'.$file_name.'.csv"');
    header('Content-Type:application/octet-stream');
    header('Content-Length:'.strlen($csv));
    echo $csv;
    exit;
}

という風に実装してみた。
tempの代わりにoutputストリームに書き込む方法もあるが、
こちらは出力バッファ系もごちゃごちゃいじる必要があるので、
一手間増えるためあまり好きじゃない。

ポイントとなる関数
  • fputcsv ・・・ 行を CSV 形式にフォーマットし、ファイルポインタに書き込む
  • stream_get_contents ・・・ 残りのストリームを文字列に読み込む

0 件のコメント:

コメントを投稿