Help us understand the problem. What is going on with this article?

CakePHPのCsvView プラグインでお手軽CSV出力

More than 3 years have passed since last update.

公式
https://github.com/FriendsOfCake/cakephp-csvview

以下の説明はほぼ公式のドキュメントと内容は同じです。
以下の内容はは

  • CakePHP 3.3
  • CsvView 3.2

の場合です。

主な機能

  • 配列からCSV出力
  • QueryからCSV出力
  • ヘッダー、フッタを指定化
  • CSV文字コードの指定

インストールと有効化

インストール

composer require friendsofcake/cakephp-csvview:~3.0

インストール後、config/bootstrap.phpへプラグイン読み込みを追加

config/bootstrap.php
Plugin::load('CsvView');

動作確認

以下のコードをControllerに書いて確認

public function export()
{
    $data = [
        ['a', 'b', 'c'],
        [1, 2, 3],
        ['あなた', 'と', 'わたし'],
    ];
    $_serialize = ['data'];

    $this->viewBuilder()->className('CsvView.Csv');
    $this->set(compact('data','_serialize'));
}

以下が表示されるはずです。ちなみに、CsvView.CSvのところをJsonに変える結果がjsonになります。

a,b,c
1,2,3
あなた,と,わたし

まとめると

  • $_serialize にデータの変数名を指定
  • viewBuilder()で`CSvView.CSVを指定
  • $this->setで$data$_serialize をビューに渡す

でCSVが出力できます。
また、データは複数指定する事ができ、以下のコードは同じ結果になります。

public function export()
{
    $data = [['a', 'b', 'c']];
    $data_two = [[1, 2, 3]];
    $data_three = [['あなた', 'と', 'わたし']];

    $_serialize = ['data', 'data_two', 'data_three'];

    $this->viewBuilder()->className('CsvView.Csv');
    $this->set(compact('data', 'data_two', 'data_three', '_serialize'));
}

ヘッダとフッター

ヘッダとフッターをつけるには、_header_footerに配列でセットします。

public function export()
{
    $data = [
        ['a', 'b', 'c'],
        [1, 2, 3],
        ['あなた', 'と', 'わたし'],
    ];
    $_serialize = ['data'];
    $_header = ['Column 1', 'Column 2', 'Column 3'];
    $_footer = ['Totals', '400', '$3000'];

    $this->viewBuilder()->className('CsvView.Csv');
    $this->set(compact('data','_serialize', '_header', '_footer'));
}
"Column 1","Column 2","Column 3"
a,b,c
1,2,3
あなた,と,わたし
Totals,400,$3000

ファイルでのダウンロード

大抵はCSVが画面に表示されてもあまり嬉しくなく、ファイルにダウンロードしたいと思います。以下のコードに変更します。

public function export()
{
    $data = [
        ['a', 'b', 'c'],
        [1, 2, 3],
        ['あなた', 'と', 'わたし'],
    ];
    $_serialize = ['data'];
    $_header = ['Column 1', 'Column 2', 'Column 3'];
    $_footer = ['Totals', '400', '$3000'];

    /**
     * Windows対応
     */
    $_csvEncoding = 'CP932';
    $_newline = "\r\n";
    $_eol = "\r\n";

    $this->response->download('my_file.csv');
    $this->viewBuilder()->className('CsvView.Csv');
    $this->set(compact('data', '_serialize', '_header', '_footer', '_csvEncoding', '_newline', '_eol'));
}

$this->response->download('my_file.csv') でブラウザにダウンロードを指定します。
また、大抵はExcelで開きたいと言う要望がありますので、文字コードをWindows-SJIS、改行をCRLFに変更します。

  • _csvEncoding : CSV文字の文字コード。iconvで変換。CP932がWindowsの文字コード

DBから直接CSV出力

Postsテーブルの内容から直接CSVを出力する場合。

public function export()
{
    $posts = $this->Posts->find('all');
    $_serialize = 'posts';
    $_header = ['Post ID', 'Title', 'Created'];
    $_extract = [
        'id',
        function ($row) {
            return $row['title'];
        },
        'created'
    ];

    $this->viewBuilder()->className('CsvView.Csv');
    $this->set(compact('posts', '_serialize', '_header', '_extract'));
}

_serializeにQuery、_extractに出力したいカラム名を指定すれば、Queryが実行されCSVが出力されます。

_extractは CakePHPの Hash::extract()を利用しており、callableを利用できるので値を編集できます。

複雑なCSVを出力する

_serializeにnull を指定すると、templateを利用して自前でCSVを出力できます。
以下の場合、テンプレートはcsvディレクトリにあるものが指定され、 src/Template/Posts/csv/export.ctpになります。

src/Controller/PostsController.php
public function export()
{
    $posts = $this->Post->find('all');
    $_serialize = null;
    $this->viewBuilder()->className('CsvView.Csv');
    $this->set(compact('posts', '_serialize'));
}

以下のように、CSVのデータ部分のみを出力するTemplateを作成します。

src/Template/Posts/csv/export.ctp
foreach ($posts as $post) {
    echo $post->id . ',' . $post->title . ',' . $post->created . PHP_EOL;
}

CSV制御オプション

CSVの出力を変更するのに、以下の変数が利用できます。

変数名 デフォルト 説明
_delimiter ',' データ区切り文字
_enclosure '"' データのクオート文字
_eol "\n" データ改行文字
_newline "\n" 新規行
_bom false BOMを出力するか
_null '' データがnullの表示値
_dataEncoding 'UTF-8' データの文字コード。iconvを利用
_csvEncoding 'UTF-8' csv表示の文字コード。iconvを利用
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away