質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.92%

PHPでCSVインポートについて

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 744

ssk

score 288

CSVをインポートする際

CSV上での表示
公開 or 非公開

データベース上での表示
1 or 2

の場合、整形してからインサートすると思います。

下記でDBへインポートはできているのですが
もっと効率的な書き方はないでしょうか?

セレクトボックスとチェックボックスを正規化しているため
データベース上は数字、CSV上はテキストになっています。

CSVのデータをarray_searchで探して
該当するデータがある場合はそのidを代入するようにしています。

40項目以上、セレクトボックスorチェックボックスがあるので
ifを何行も生成しなければいけないのかな、、、と悩んでいます。

<?php
use App\Controller\AppController;
use Cake\Core\Configure;
use Cake\ORM\TableRegistry;
use Cake\ORM\Entity;
use Cake\Event\Event;
use Cake\I18n\Time;
use Cake\Core\Exception\Exception;

$DatacklistsTable = TableRegistry::get('Datacklists');

$DaldataTable07 = TableRegistry::get('Daldata07s');
$DaldataTable09 = TableRegistry::get('Daldata09s');
$DaldataTable11 = TableRegistry::get('Daldata11s');
$DaldataTable15 = TableRegistry::get('Daldata15s');
$DaldataTable16 = TableRegistry::get('Daldata16s');

$DaldataTable07 = $DaldataTable07->find()->combine('dal07_id','name')->toArray();
$DaldataTable09 = $DaldataTable09->find()->combine('dal09_id','name')->toArray();
$DaldataTable11 = $DaldataTable11->find()->combine('dal11_id','name')->toArray();
$DaldataTable15 = $DaldataTable15->find()->combine('dal15_id','name')->toArray();
$DaldataTable16 = $DaldataTable16->find()->combine('dal16_id','name')->toArray();

//カラム数の判定のために利用
$columnCnt = $DatacklistsTable->find()->contain (['Daldata11s','Daldata15s','Daldata16s'])->first()->toArray();

$header = [];
$str = "::";

foreach ($csvfile as $row) {
        // 空行はスキップ
        if ($row === array(null)) {
            continue;
        }

        if (empty($header)) {
            for ($i = 0; $i < count($row); $i++) {
                $row[$i] = substr($row[$i], (strpos($row[$i], $str) + strlen($str)));
            }
            $header = $row;
            continue;
        }

        $data = array_combine($header, $row);

        //////////////////////////////////////////////////
        //カラム数が異なる無効なフォーマット
        //////////////////////////////////////////////////
        if (count($data) !== count($columnCnt)) {
            throw new Exception('カラム数が不正です。');
        }

        //////////////////////////////////////////////////
        //FALSEを代入しておけば
        //////////////////////////////////////////////////
        $id         = isset($data['id']) && $data['id'] !== '' ? $data['id'] : FALSE;
        $dal07         = isset($data['dal07']) && $data['dal07'] !== '' ? $data['dal07'] : FALSE;
        $dal08         = isset($data['dal08']) && $data['dal08'] !== '' ? $data['dal08'] : FALSE;
        $dal09         = isset($data['dal09']) && $data['dal09'] !== '' ? $data['dal09'] : FALSE;
        $dal10         = isset($data['dal10']) && $data['dal10'] !== '' ? $data['dal10'] : FALSE;
        $dal11s     = isset($data['dal11']) && $data['dal11'] !== '' ? $data['dal11'] : FALSE;
        $dal15s     = isset($data['dal15']) && $data['dal15'] !== '' ? $data['dal15'] : FALSE;
        $dal16s     = isset($data['dal16']) && $data['dal16'] !== '' ? $data['dal16'] : FALSE;

        //////////////////////////////////////////////////
        //セレクトボックスが空白の場合は0を代入する
        //array_searchで検索にヒットしない場合はfalseが返されて0を代入
        //////////////////////////////////////////////////
        if(isset($dal07) && $dal07 !== FALSE){
            $dal07 = array_search($data['dal07'],$DaldataTable07);
            if($dal07 === FALSE){
                $dal07 = 0;
            }
        }else{
            $dal07 = 0;
        }


        if(isset($dal09) && $dal09 !== FALSE){
            $dal09 = array_search($data['dal09'],$DaldataTable09);
            if($dal09 === FALSE){
                $dal09 = 0;
            }
        }else{
            $dal09 = 0;
        }


        $dal07 = ['dal07' => $dal07];
        $dal09 = ['dal09' => $dal09];

        $saveData = array_replace($dal07,$dal09);

        //////////////////////////////////////////////////
        //半角スペース、全角スペースがあるとarray_searchに引っかからない
        //チェックボックスは半角・全角スペースは削除する
        //////////////////////////////////////////////////
        if(isset($dal11s) && $dal11s !== FALSE){
            $dal11s  = preg_replace("/( | )/", "", $dal11s );
            $dal11s = explode(';',$dal11s);
            foreach($dal11s as $key => $value){
                $values = array_search($value,$DaldataTable11);
                if($values){
                    $ids[] =  $values;
                }
            }
            $saveData['daldata11s']['_ids'] = $ids;
        }else{
            $saveData['daldata11s']['_ids'] = [];
        }

        if(isset($dal15s) && $dal15s !== FALSE){
            $dal15s  = preg_replace("/( | )/", "", $dal15s );
            $dal15s = explode(';',$dal15s);
            foreach($dal15s as $key => $value){
                $values = array_search($value,$DaldataTable15);
                if($values){
                    $ids[] =  $values;
                }
            }
            $saveData['daldata15s']['_ids'] = $ids;
        }else{
            $saveData['daldata15s']['_ids'] = [];
        }

        if(isset($dal16s) && $dal16s !== FALSE){
            $dal16s  = preg_replace("/( | )/", "", $dal16s );
            $dal16s = explode(';',$dal16s);
            foreach($dal16s as $key => $value){
                $values = array_search($value,$DaldataTable16);
                if($values){
                    $ids[] =  $values;
                }
            }
            $saveData['daldata16s']['_ids'] = $ids;
        }else{
            $saveData['daldata16s']['_ids'] = [];
        }

        //////////////////////////////////////////////////
        //チェックボックス配列から削除
        //そのままでも大丈夫だけど、見た目が悪い
        //////////////////////////////////////////////////
        unset($saveData['dal11']);
        unset($saveData['dal15']);
        unset($saveData['dal16']);

        //上記で整形したデータを1件ずつ「新規作成」or「更新」
        $result = $DatacklistsTable->findById($id)->first();
        if($result){
            //更新
            $datacklist     = $DatacklistsTable->get($id, ['contain' => ['Daldata11s','Daldata15s','Daldata16s']]);
            $datacklist     = $DatacklistsTable->patchEntity($datacklist,$saveData,['associated' => ['Daldata11s','Daldata15s','Daldata16s']]);
            //debug($datacklist);
            if(!$datacklist->errors()){
                $importResult     = $DatacklistsTable->save($datacklist);
                if($importResult){
                    $this->Flash->set($importResult->id.'.'.$importResult->dal02.' 更新', []);
                }
            }else{
                    $this->Flash->set($id.'.'.$datacklist->dal02.' 失敗', []);
            }
        }else{
            //新規追加
            $datacklist     = $DatacklistsTable->newEntity($saveData,['associated' => ['Daldata11s','Daldata15s','Daldata16s']]);
            if(!$datacklist->errors()){
                $importResult     = $DatacklistsTable->save($datacklist);
                if($importResult){
                    $this->Flash->set($importResult->id.'.'.$importResult->dal02.' 新規追加', []);
                }
            }else{
                $this->Flash->set($id.'.'.$datacklist->dal02.' 失敗', []);
            }
        }    
}

$DatacklistsTable->connection()->commit();
?>

追記

$saveData['daltada11s']['_ids'] = $this->Functions->_searchCheckBox($dal11s,$data,'daldata11s',$DaldataTable11);
$saveData['daltada15s']['_ids'] = $this->Functions->_searchCheckBox($dal15s,$data,'daldata15s',$DaldataTable15);
$saveData['daltada16s']['_ids'] = $this->Functions->_searchCheckBox($dal16s,$data,'daldata16s',$DaldataTable16);
public function _searchCheckBox($values,$datas,$key,$table){
        if(isset($values) && $values !== FALSE){
            //////////////////////////////////////////////////
            //半角スペース、全角スペースがあるとarray_searchに引っかからない
            //チェックボックスは半角・全角スペースは削除する
            //////////////////////////////////////////////////
            $values  = preg_replace("/( | )/", "", $values);
            $values = explode(';',$values);

            foreach($values as $key => $value){
                $values = array_search($value,$table);
                    if($values){
                        $ids[] =  $values;
                    }
                }
                $values = $ids;
            }else{
                $values = [];
        }
            return $values;
    }
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

きれいに書けていますね。ただ、以下の2点を改善すれば更に効率的な書き方になると思います。

  1. 処理が冗長です。同じ処理はまとめましょう。全体の流れが分かりにくいです。
  2. CSVデータが具体的にどのようなものか分からないので、どのような処理をすべきか検討できません。人に見せるときはデータについて説明しましょう。話は少しずれますが、下記の参考サイトに目を通すとためになります。
    (参考:最低限書いておきたいPHPのDocコメント
    (参考:phpDocumentor

【1.の例】

// 同じ処理をしている
        if(isset($dal07) && $dal07 !== FALSE){
            $dal07 = array_search($data['dal07'],$DaldataTable07);
            if($dal07 === FALSE){
                $dal07 = 0;
            }
        }else{
            $dal07 = 0;
        }


        if(isset($dal09) && $dal09 !== FALSE){
            $dal09 = array_search($data['dal09'],$DaldataTable09);
            if($dal09 === FALSE){
                $dal09 = 0;
            }
        }else{
            $dal09 = 0;
        }

↓↓↓↓↓↓

// まとめる
public function _hoge($dal,$data,$key,$DaldataTable)
{
    if(isset($dal) && $dal !== FALSE){
        $dal = array_search($data[$key],$DaldataTable);
        if($dal === FALSE){
            $dal = 0;
        }
    }else{
        $dal = 0;
    }
    return $dal;
}

public function main()
{
    $dal07 = $this->_hoge($dal07,$data,'dal07',$DaldataTable07)
    $dal09 = $this->_hoge($dal09,$data,'dal09',$DaldataTable09)
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/04/06 22:40

    ありがとうございます。

    $dal07 = $this->_hoge($dal07,$data,'dal07',$DaldataTable07)
    ↑こちらを参考に処理をまとめることができました。


    下記の処理はまとめることはできますか?
    returnの処理が配列になるため、悩んでいます。。

    if(isset($dal11s) && $dal11s !== FALSE){
    $dal11s = preg_replace("/( | )/", "", $dal11s );
    $dal11s = explode(';',$dal11s);
    foreach($dal11s as $key => $value){
    $values = array_search($value,$DaldataTable11);
    if($values){
    $ids[] = $values;
    }
    }
    $saveData['daldata11s']['_ids'] = $ids;
    }else{
    $saveData['daldata11s']['_ids'] = [];
    }

    キャンセル

  • 2017/04/06 22:52

    チェックボックスfunctionを追記しました。
    どうでしょう、、、助言いただければ幸いです。

    キャンセル

  • 2017/04/07 00:10

    考え方は合っています。
    変数の対応関係やreturnするものを再度確認してください。

    キャンセル

  • 2017/04/07 00:48

    ありがとうございます!
    助かりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.92%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る