LoginSignup
6
0

More than 3 years have passed since last update.

CAKEPHP3でCSV読込

Last updated at Posted at 2019-07-31

モデルなしフォーム作成

src/Form/HogeCsvForm.php

<?php
namespace App\Form;

use Cake\Form\Form;
use Cake\Form\Schema;
use Cake\Validation\Validator;

class HogeCsvForm extends Form
{
    protected function _buildSchema(Schema $schema)
    {
        return $schema->addField('csv', ['type' => 'file']);
    }

    protected function _buildValidator(Validator $validator)
    {
        $validator->provider('upload', \Josegonzalez\Upload\Validation\DefaultValidation::class);
        $validator->add('csv', 'fileFileUpload', [
            'rule' => ['isFileUpload'],
            'message' => 'アップロードに失敗しました。',
            'provider' => 'upload'
        ])->add('csv', 'fileBelowMaxSize', [
            'rule' => ['isBelowMaxSize', 10240000],
            'message' => 'ファイルサイズが大きすぎます。',
            'provider' => 'upload'
        ])->add('csv', 'fileType', [
            'rule' => ['mimeType', ['text/plain']],
            'message' => 'ファイル形式が違います。'
        ]);
    }

    protected function _execute(array $data)
    {
        return true;
    }

}

Controller作成

src/Controller/HogesController.php

<?php
namespace App\Controller\Manage;

use App\Controller\AppController;
use App\Form\HogeCsvForm; // モデルなしフォームロード
use Cake\Filesystem\Folder;  // Folderユーティリティロード

class HogesController extends AppController
{
    public function initialize()
    {
        parent::initialize();
        $this->loadComponent('Csv'); // CSVコンポートロード
    }
    public function csv()
    {
        $hogesCsv = new HogesCsvForm();
        if ($this->request->is(['patch', 'post', 'put'])) {
            if ($hogesCsv ->execute($this->request->getData())) {
                // ファイルコピー
                $path = ROOT . DS . 'uploadfiles' . DS . 'tmp';
                $folder = new Folder();
                $folder->create($path);
                $file = $path . DS . sha1(uniqid(mt_rand(), true)) . '.csv';
                if (move_uploaded_file($this->request->getData('csv.tmp_name'), $file)) {
                    chmod($file, 0644);

                    // CSVデータ取込
                    $csvData = $this->Csv->getCsv($file);

                    // データ整形
                    $data = [];
                    foreach ($csvData as $vol) {
                        $data[] = [
                            'real_estate_id' => 0,
                            'aggregated_at'  => date('Y-m-d'),
                            'incomes'        => $vol['2'],
                            'expenses'       => $vol['3'],
                        ];
                    }

                    // データ登録
                    $this->loadModel('Hoges');
                    $entities = $this->MonthlyBalances->newEntities($data);
                    $result = $this->MonthlyBalances->saveMany($entities);

                    unlink($file);
                    $this->Flash->success('登録しました。');
                }else{
                    $this->Flash->error('登録に失敗しました。');
                }
            } else {
                $this->Flash->error('登録に失敗しました。');
            }
        }
        $this->set('hogesCsv', $hogesCsv);
    }
}

view作成

src/Template/Hoges/csv.ctp

<div>
<?= $this->Form->create($hogesCsv, ['type' => 'file']) ?>
    <fieldset>
        <legend><?= __('CSV登録') ?></legend>
        <?php
        echo $this->Form->control('csv', ['type' => 'file']);
        ?>
    </fieldset>
    <?= $this->Form->button(__('Submit')) ?>
<?= $this->Form->end() ?>
</div>

CSVデータ読込コンポーネント作成

Controller\Component\CsvComponent.php

<?php
namespace App\Controller\Component;

use Cake\Controller\Component;
use Cake\Controller\ComponentRegistry;
use \SplFileObject;

/**
 * Csv component
 */
class CsvComponent extends Component
{

    /**
     * Default configuration.
     *
     * @var array
     */
    protected $_defaultConfig = [];

    public function getCsv($csvfile, $mode='sjis')
    {
        // ファイル存在確認
        if (!file_exists($csvfile)) {
            return false;
        }

        // 文字コードを変換しながら読み込めるようにPHPフィルタを定義
        if ($mode === 'sjis') {
            $filter = 'php://filter/read=convert.iconv.cp932%2Futf-8/resource='.$csvfile;
        } elseif ($mode === 'utf16') {
            $filter = 'php://filter/read=convert.iconv.utf-16%2Futf-8/resource='.$csvfile;
        } elseif ($mode === 'utf8') {
            $filter = $csvfile;
        }

        // SplFileObject()を使用してCSVロード
        $file = new SplFileObject($filter);
        if ($mode === 'utf16') {
            $file->setCsvControl("\t");
        }
        $file->setFlags(
            SplFileObject::READ_CSV |
            SplFileObject::SKIP_EMPTY |
            SplFileObject::READ_AHEAD
        );

        // 各行を処理
        $records = [];
        foreach ($file as $i => $row)
        {
            // 1行目はスキップ
            if ($i===0) {
                continue;
            }

            // 2行目以降はデータ行として取り込み
            $records[] = $row;
        }
        return $records;
    }
}

参考

PHPでCSV読み込み関数の決定版を作ってみた。

6
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
0