cakePHP,csvエクスポート用のtraitを編集する.

前回の記事で多重にTraitをuseする方法について紹介しました. 今回はこの機能を使ってcsvエクスポート機能を実装していきたいと思います.

基本的なTempパスの設定,ファイルの編集&データの追加などは基本的にcsvで共通な処理となりますので,この機能を持つtraitを親とし,データの部分を編集するTraitでそれをUseして,コントローラに取り込むという流れとなります.

以下がまず基本となるCSVの編集を担うTraitです.

trait CsvTrait {
    abstract protected function getDatas();
    abstract protected function getFileName();

    private function createCsv() {
        $temp_dir = sys_get_temp_dir();
        $csv_file_path = tempnam($temp_dir, 'temp_csv');
        $fp = fopen($csv_file_path, 'w');

        if ($fp === false) {
            fclose($fp);
            throw new \Exception("Failed to open {$temp_csv_file_path}.");
        }
        $this->file_path = $csv_file_path;
        fclose($fp);
    }

    private function writeCsv(){
        $file_path = $this->file_path;
        $fp = fopen($file_path, 'a');
        $datas = $this->getDatas();

        foreach($datas as $row) {
            if(fputcsv($fp, $row) === false) {
                fclose($fp);
                throw new \Exception("Failed to write data into {$file_path}.");
            }
        }
        fclose($fp);
    }

    public function downloadCsv(){
        $this->createCsv();
        $this->writeCsv();

        $file_name = $this->getFileName();
        return $this->getResponse()
            ->withCharset('UTF-8')
            ->withType('csv')
            ->withFile(
                $this->file_path,
                [
                    'download' => true,
                    'name' => $file_name
                ]
            );

    }
}

これを継承してCsvにユーザー名を追加していくTraitを作ります.

trait UserCsvTrait {
    use CsvTrait;
    protected function getDatas() {
        return $this->Users->find()->extract('name');
    }
    protected function getFileName() {
        return "users.csv";
    }
}

これをコントローラーに追加すると,

class UsersController extends AppController{
   use UserCsvTarit; // use
   // 以下省略
}

パブリックとしていたdownloadCsvが追加されるので,アクション等でそのメソッドを呼べばCSVエクスポート機能が実装できるはずです.