たきゃはしです

もう日常ブログにしよう

CakePHP - CSVダウンロード(エクスポート)機能を実装する『CSV Helper』 まとめ


CakePHP2対応したのCSVヘルパーはこちらです。
FastCSV


ヘッダだとか文字化けで取っつき難いCSV関連


最初に言っておきます、CSV Helperはとても易しく使いやすいです。
CSV Helper (PHP 5)


ザッとマニュアルを見てから思い通りの実装・出力まで30分程度でした。
それでは、さっそく使い方を説明します。


1.まず、「app/views/helpers/」に「csv.php」を作成して
以下のソースをそのままコピペしてください。

<?php

class CsvHelper extends AppHelper {

    var $delimiter = ',';
    var $enclosure = '"';
    var $filename = 'Export.csv';
    var $line = array();
    var $buffer;

    function CsvHelper() {
        $this->clear();
    }

    function clear() {
        $this->line = array();
        $this->buffer = fopen('php://temp/maxmemory:'. (5*1024*1024), 'r+');
    }

    function addField($value) {
        $this->line[] = $value;
    }

    function endRow() {
        $this->addRow($this->line);
        $this->line = array();
    }

    function addRow($row) {
        fputcsv($this->buffer, $row, $this->delimiter, $this->enclosure);
    }

    function renderHeaders() {
        header("Content-type:application/vnd.ms-excel");
        header("Content-disposition:attachment;filename=".$this->filename);
    }

    function setFilename($filename) {
        $this->filename = $filename;
        if (strtolower(substr($this->filename, -4)) != '.csv') {
            $this->filename .= '.csv';
        }
    }

    function render($outputHeaders = true, $to_encoding = null, $from_encoding = "auto") {
        if ($outputHeaders) {
            if (is_string($outputHeaders)) {
                $this->setFilename($outputHeaders);
            }
            $this->renderHeaders();
        }
        rewind($this->buffer);
        $output = stream_get_contents($this->buffer);
        if ($to_encoding) {
            $output = mb_convert_encoding($output, $to_encoding, $from_encoding);
        }
        return $this->output($output);
    }
}

※元ソースでは文末に『?>』がついているが、これは取り除いておくこと。


2.次に、CSVダウンロード機能を実装したいコントローラに任意の名前でメソッドを作成します。

//CSVダウンロード機能を実装したいコントローラ:users_controller.php 
//メソッド:download_csv 
<?php

class UsersController extends AppController {

    var $name = 'Users';
    var $helpers = array('Html', 'Form', 'Csv'); //CSVヘルパーを設定します

    function download_csv() {
        Configure::write('debug', 0); // 警告を出さない
        $this->layout = false;
        $filename = 'EXP_ユーザー_' . date('YmdHis'); // 任意のファイル名
        $genders = array('1' => '男性', '2' => '女性');
        $th = array('id', 'username', 'gender', 'status'); // 表の一行目を作成
        $td = $this->User->find('all', array('fields' => $th)); //表の内容を取得
        $this->set(compact('filename', 'genders', 'th', 'td'));
    }


3.最後にビューを作成します。

// views/users/download_csv.ctp
<?php
$csv->addRow($th);
foreach ($td as $t) {
    $csv->addRow($t['User']);
}
$csv->setFilename($filename);
echo $csv->render(); // 文字化けする場合は、『echo $csv->render(true, 'sjis', 'utf-8');』


これだけでCSVファイルの生成機能は完成です。
例では『ドメイン/users/download_csv』 へアクセスすればCSVデータのダウンロードが可能です


しかし、データベースの設計によってはさらに手を加える必要があるかもしれません。
例えば、性別などを1か2の数値で保存している場合です。これでは男性か女性かの区別が出来ません。


でも安心してください。
そのような場合は以下のようにビューを変更します。

// views/users/download_csv.ctp
<?php
$csv->addRow($th);
foreach ($td as $t) {
    //$csv->addRow();
    $csv->addField($t['User']['id']);
    $csv->addField($t['User']['username']);
    $csv->addField($genders[$t['User']['gender']]); // 予めセットしておいた配列により、数値から男性・女性に切り替える
    $csv->addField($t['User']['status']);
    $csv->endRow();
}
$csv->setFilename($filename);
echo $csv->render(); // 文字化けする場合は、『echo $csv->render(true, 'sjis', 'utf-8');』


上のように表を行単位で設定する方法で、より柔軟なCSVデータを作成することが可能です。


また、文字化けしてしまう場合は、ビューの最後にある
>echo $csv->render();

>echo $csv->render(true, 'sjis', 'utf-8');
に変更してあげてください。


        • -

開発環境
PHP 5.3
CakePHP 1.3.7 〜 1.3.9