2017-04-13 3 views
1

レコードを複数のデータベーステーブルにインポートするスクリプトが1つの親エンティティ(アドレス)に関連付けられています。CSVからのインポート、レコードがすでに存在しています。他の場合は成功しません。

アドレスが既に存在する場合は、追加の列はcsvに従って更新する必要があります。他のすべてのエンティティについても同じカウントです。カウンター($exist++)を増やすか、配列($existingRecords)を既存のレコードで埋める必要があります。

レコードで必須フィールドが空の場合、そのレコードを別の配列($failedRecords)に追加するか、別のカウンタ($failed++)を増やす必要があります。

アドレスがまだ存在せず、すべてのフィールドで作成する必要がある場合は、カウンタ($successful++)だけを増やす必要があります。

最終的に私はユーザーのフィードバックのために、失敗した、成功した、そして既に存在する(しかし更新された)レコードの数を示す配列$resultを持っています。

私の現在のスクリプトをあまりにも邪魔することなく、すっきりとした方法でこれを実装するにはどうすればよいですか?現在レコードが存在する場合、レコードが既に存在する場合は$existカウンタが増加しますが、$successfulカウンタも増加します。レコードがすでに存在する場合は$existカウンタを増やし、レコードがまだ存在する場合は$successfulカウンタだけ増やします追加する必要があり、正常に追加されました。 $failedカウンターでも同じです。ここで

(私が試したものと)私のスクリプトです:

public function import(CsvFile $csv) { 
    $root = __DIR__.'/../../../../../'; 
    $file = $root.'var/data/'.$csv->getCsvName(); 
    $fp = fopen($file, "r"); 

    $batchSize = 25; 
    $header = null; 
    $successful = 0; 
    $failed = 0; 
    $exist = 0; 
    $results = []; 

    while ($row = fgetcsv($fp, null, ";")) { 
     if ($header === null) { 
      $header = $row; 
      continue; 
     } 

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

     // cast all values to correct data types 
     foreach ($record as $key => &$value) { 
      if (strpos($key, 'datum') !== false || 
       strpos($key, 'tijdstip') !== false && 
       strlen($value) == 8 && 
       is_numeric($value) 
      ) { 
       $value = \DateTime::createFromFormat('Ymd', $value); 
      } 

      if ($value === "") { 
       $value = null; 
      } 

      if (is_numeric($value)) { 
       intval($value) == $value ? $value = (int)$value : $value = (float)$value; 
      } 
     } 

     // required fields 
     if (!$record['name'] || 
      !$record['surname'] || 
      !$record['email'] || 
      !$record['phone'] || 
      !$record['street'] || 
      !$record['houseNo'] || 
      !$record['town'] || 
      !$record['postcode'] || 
      !$record['location'] || 
      !$record['lecture'] || 
      !$record['session'] || 
     ) { 
      $failed++; 
      continue; 
     } 

     $student = $this->em->getRepository(Student::class)->findStudent(
      $record['name'], $record['surname'], 
      $record['email'], $record['phone'] 
     ); 

     if (!$student) { 
      $student = new Student(); 
      $student->setName($record['name']); 
      $student->setSurname($record['surname']); 
      $student->setEmail($record['email']); 
      $student->setPhone($record['phone']); 
     } else { 
      $exist++; 
     } 
     $student->setAge($record['age']); 
     $student->setLength($record['length']); 

     $address = $this->em->getRepository(Address::class)->findOneBy([ 
      'street' => $record['street'], 
      'houseNo' => $record['houseNo'], 
      'town' => $record['town'], 
      'postcode' => $record['postcode'], 
     ); 

     if (!$address) { 
      $address = new Address(); 
      $address->setStreet($record['street']); 
      $address->setHouseNo($record['houseNo']); 
      $address->setPostcode($record['postcode']); 
      $address->setTown($record['town']); 
     } 
     $student->setAddress($address); 

     $lecture = $this->em->getRepository(Lecture::class)->findOneBy([ 
      'location' => $record['location'], 
      'lecture' => $record['lecture'], 
      'session' => $record['session'], 
     ]); 

     if (!$lecture) { 
      $lecture = new Lecture(); 
      $lecture->setLocation($record['location']); 
      $lecture->setLecture($record['lecture']); 
      $lecture->setSession($record['session']); 
     } 
     $lecture->setTime($record['time']); 
     $lecture->setSubject($record['subject']); 
     $student->setLecture($lecture); 

     $validationErrors = $this->validator->validate($student); 
     if (!count($validationErrors)) { 
      $this->em->persist($student); 
      $successful++; 
     } 

     if (($successful % $batchSize) == 0) { 
      $this->em->flush(); 
     } 
    } 
    fclose($fp); 

    $csv->setImported(true); 

    $this->em->persist($csv); 
    $this->em->flush(); // Also persist objects that did not make up an entire batch 

    $results['successful'] = $successful; 
    $results['failed'] = $failed; 
    $results['exist'] = $exist; 

    return $results; 
} 

答えて

1

現在のレコードが既存のレコードである場合にのみ、TRUEに設定されたフラグで既存のレコードカウンタを置き換え、最後に使用してレコードを保持することができます。 あなたは各ループの最初にFALSEにフラグを設定することができます。

while ($row = fgetcsv($fp, null, ";")) { 
     $existingRecordFlag = FALSE; // initialize the flag for the current record 

、代わりにカウンターでそれを更新:

if (!$student) { 
     $student = new Student(); 
     $student->setName($record['name']); 
     $student->setSurname($record['surname']); 
     $student->setEmail($record['email']); 
     $student->setPhone($record['phone']); 
    } else { 
     $existingRecordFlag = TRUE; //update the flag 
    } 

、ユーザはフラグの値をチェックし持続し、に従って前

また、更新される可能性のある既存のレコードをバッチカウンタに追加することもできますし、su厄介なもの

if ((($successful+$exist) % $batchSize) == 0) { 
     $this->em->flush(); 
    } 
0

あなたのブロックでは、既存の/非常に簡単にカウンター失敗した可能性がありアドレス取り扱い:

$exist++; 
if (!$address) { 
    $exist--; 
    $successful++; 

    //... 
} 

これは常に増加しますが存在しているカウンターですが、アドレスが空の場合は戻って新しいアドレスカウンターを増やしてください。あるいは、array_push($record)array_pop($record)を使って、現在のレコードをリストに追加/削除することもできます。レコードを複数の配列に保持し、メモリ不足のエラーが発生する可能性があるため、メモリの問題が発生する可能性があります。

必須フィールドが不足している場合は、後で$アドレスをチェックして、空でないか無効なデータが含まれているかどうかを確認してから、カウンタを増やしてフィールドを更新する必要があります。 必要な場合

関連する問題