株式会社プロネット

 

WEBシステム開発、ITコンサルティング、自社サービス、教育事業 - これからのビジネスへのIT活用ソリューションをご提案致します。

CakePHPからCSVファイルを出力する

2015.1.7(Wed) 19:35 | CakePHP | sofuku

CSVヘルパーを利用すると、CakePHPでCSVファイルの出力が簡単にできます。

環境

PHP:5.3.3
CakePHP:2.4.6

こちらの作者さんのgithubからダウンロードもできるようです。  

1.Helperクラス作成

app/View/Helper配下に「CsvHelper.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) {
        // IEでのファイル名文字化け対策
        $this->filename = mb_convert_encoding($filename, 'sjis', 'utf-8');
        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);
    }
}

  ここでハマったポイントは、出力したCSVファイルの名前がIEだと文字化けしてしまう、という問題。 そのため、↑のコード39行目で$filenameをエンコーディングするように修正してあります。 CSV文字化けサンプル

2.ControllerでCSVダウンロード用のメソッドを作成

次に、作成したCSVヘルパーを使用してダウンロード用のメソッドを使用したいControllerに記述していきます。

class TestsController extends AppController {
    // Csvヘルパーを読み込む
    var $helpers = array('Html', 'Form', 'Csv');

    function download_csv() {
        $this ---> layout = false;
        $filename = 'ダウンロードテスト' . date('YmdHis');

        // 表の一行目を作成
        $th = array('テストID', 'ユーザー名', 'メールアドレス');
        // 表の内容を取得
        $column = array('id', 'username', 'mail_address')
        $td = $this->Test->find('all', array('fields' => $column));
        $this -> set(compact('filename', 'th', 'td'));
    }
}

3.Viewファイルで出力内容を記載

app/View/Tests/download_csv.ctpを作成します。

// ヘッダー行設定
$this--->Csv->addRow($th);
foreach($td as $t) {
$this->Csv->addField($t['Test']['id']);

$this->Csv->addField($t['Test']['username']);

$this->Csv->addField($t['Test']['mail_address']);

// 行の終わりを宣言
$this->Csv->endRow();
}
$this->Csv->setFilename($filename);
echo $this->Csv->render(true, 'sjis', 'utf-8');

これで/tests/download_csv/にアクセスするとCSVファイルがダウンロードできるようになります。