2015年8月30日日曜日

CakePHP:CSVアップロード時に既存データとマッチングしてデータ格納

CakePHPで既存データがある場合に、そのデータとマッチングしてデータを格納する方法(基本的)です。

1. CSVアップロードの作成
[Controller] アクション名が「csv2」の場合
public function csv2(){
}
※空関数作成

[View] csv2.ctp

       

               
       
        echo $this->Form->create('Hospital',array('action'=>'import2','type'=>'file'));
        echo $this->Form->input('CsvFile',array('label'=>'','type'=>'file'));
        echo $this->Form->end('Upload');

        ?>
       






2. import2関数を作成
[Controller]
public function import2(){
            if($this->request->is('post')){
                $up_file = $this->data['Hospital']['CsvFile']['tmp_name'];
                $fileName = 'post.csv';
                if(is_uploaded_file($up_file)){
                    move_uploaded_file($up_file, $fileName);
                    $this->Hospital->loadCSV2($fileName);
                    $this->Session->setFlash('Uploaded');
                    $this->redirect(array('action'=>'index'));
                }
            }
        }

3. モデルにCSVの格納処理を書く
[Model]
public function loadCSV2($filename){
            $this->begin();
            try{
                //$this->deleteAll('1=1',false);
                $csvData = file($filename,FILE_SKIP_EMPTY_LINES | FILE_IGNORE_NEW_LINES);

                //マッチングしたいデータの取得
                $hospitals = $this->find('all',
                        array(
                                'fields' => array('id', 'tel'),
                                'recursive' => -1,
                        )

                );

                foreach($csvData as $line){
                    $record = split(',',$line);

                        //マッチングのループに入る
                        foreach($hospitals as $hospital){
                                if($hospital['Hospital']['tel'] === $record[0]){
                                        $data =array(
                                                'id' =>$hospital['Hospital']['id'],
                                                'doctor' => $record[1],
                                                'parttime' => $record[2],
                                        );
                                        $this->save($data);
                                        break;
                                }
                        }
                }
                $this->commit();
            }catch(Exception $e){
                $this->rollback();
            }
        }

アップロードするデータ形式
420-8537,16,3
420-8876,20,3



郵便番号,データ1,データ2
文字コードはUTF-8, 改行コードLF
※改行コードをLFにしないと、CSVからのデータをうまく読めません。