PHP CSV出力用クラス

PHPでCSVを作成するために作ったクラス。
CSVを扱うならleague/csvの方が便利そうだが、league/csvをインストールするのも面倒なときなどに。

サーバー上に1行ずつ保存してからダウンロード(またはコピー)しているので、大きなファイルでもメモリ上限を気にせず使える。

class OutputCSV2
{
    private $toEncoding;
    private $fromEncoding;
    private $tmpfile;

    public function __construct($to_encoding = '', $from_encoding = 'UTF-8')
    {
        $this->toEncoding = $to_encoding;
        $this->fromEncoding = $from_encoding;
        $this->tmpfile = tmpfile();
    }

    public function addData($row)
    {
        if ($this->toEncoding) {
            mb_convert_variables($this->toEncoding, $this->fromEncoding, $row);
        }

        fputcsv($this->tmpfile, $row);
    }

    public function download($filename)
    {
        $stream_meta_data = stream_get_meta_data($this->tmpfile);

        header('Content-type: text/csv');
        header("Content-disposition: attachment;filename=$filename");

        readfile($stream_meta_data['uri']);
    }

    public function save($filepath)
    {
        $stream_meta_data = stream_get_meta_data($this->tmpfile);

        copy($stream_meta_data['uri'], $filepath);
    }
}

使用例1

$data = [
    [100, 'aaa', 1000],
    [110, 'bbb', 2000],
    [120, 'ccc', 5000],
];

$csv = new OutputCSV2('SJIS-win');
$csv->addData(['id', 'name', 'price']); // 見出し行

foreach ($data as $v) {
    $csv->addData($v);
}

// ダウンロードさせる場合
$csv->download('example.csv');
exit;

// サーバーに保存する場合
$csv->save(__DIR__ . '/example.csv');

結果

id,name,price
100,aaa,1000
110,bbb,2000
120,ccc,5000

使用例2 Eloquentを使う例

csv = new OutputCSV2('SJIS-win');
$csv->addData(['id', 'name', 'price']); // 見出し行

Item::chunkById(500, function ($items) use ($csv) {
    foreach ($items as $item) {
        $csv->addData([$item->id, $item->name, $item->price]);
    }
});

// ダウンロードさせる場合
$csv->download('example.csv');
exit;

// サーバーに保存する場合
$csv->save(__DIR__ . '/example.csv');