2017-04-13 43 views
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 
    } 

则坚持用户检查值的标志,并根据前它更新计数器:

$validationErrors = $this->validator->validate($student); 
if (!count($validationErrors)) { 
    $this->em->persist($student); 
    if (!$existingRecordFlag){ 
     $successful++;   //new record 
    }else{ 
     $exist++;    //existing user 
    } 

}else{ 
     $failed++;     //failed as the validations has errors 
     continue; 
} 

也可以将现有的记录添加到批计数器,因为它们可能会被更新,它们也可以使用su坚持有用的

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

在你的块处理您可以在现有的地址/计数器失败很容易:

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

    //... 
} 

这将随时增加存在计数器,但如果地址为空则跳回,并增加新的地址计数器。或者,您可以使用array_push($record)array_pop($record)来添加/删除列表中的当前记录。这可能会导致内存问题,因为您将记录保存在多个阵列中,并且可能会遇到内存不足错误。

对于遗漏的必填字段,您必须事后检查$地址,看看它是否为空/包含无效数据,然后增加计数器/更新字段。 如果你想

相关问题