2013-11-27 1 views
0

약 23.000 행의 큰 CSV 파일을 내 MySQL 데이터베이스로 가져 오려고합니다. 모든 규칙을 한 번에 가져올 수는 없으며 작동하지 않습니다. 그래서 나는 cakePHP 트랜잭션을 사용하는 동안에도 파일을 청크로 읽을 수 있는지 궁금합니다. 이것은 지금까지 내 코드입니다 : 내가 별도의 함수에서 코드 위의 퍼팅을 한CakePHP로 청크로 CSV 파일 가져 오기

// Get data source for transactions 
$dataSource = $this->FeedImport->Product->getDataSource(); 

try{ 
    //Start Transactions 
    $dataSource->begin(); 

    // Create an empty array for the CSV data 
    $data = array(); 
    $i = 0; 

    // read each data row in the file 
    while (($row = fgetcsv($handle)) !== false) { 
     // for each header field 
     foreach ($header as $k=>$head) { 
      // Remove any special characters from $head 
      $head = preg_replace('/[^A-Za-z0-9\-]/', '', $head); 
      if(array_key_exists($head, $this->fields)){ 
       //Check the row contains an image, if so, download 
       if(preg_match('/\.(?:jpe?g|png|gif)$/i', $row[$k])){ 
        foreach($this->fields[$head] as $table => $field){ 
         $imageFileName = uniqid($supplier.'_'); 
         $data[$i][$table][][$field] = $imageFileName.'.'.end(explode('.', $row[$k])); 
         $this->__importImg($row[$k]); 
        } 
       }else{ 
        foreach($this->fields[$head] as $table => $field){ 
         if($table == 'Term'){ 
          if(isset($row[$k]) && !$this->FeedImport->Product->Term->find('first', array('conditions' => array('Term.name' => $row[$k])))){ 
           if(!$this->FeedImport->Product->Term->save(
            array(
             'name' => $row[$k] 
            ) 
           )); 
          } 
          if(isset($row[$k])) $term = $this->FeedImport->Product->Term->find('first', array('conditions' => array('Term.name' => $row[$k]))); 
          $data[$i][$table][$table][$field] = (isset($term['Term']['term_id'])) ? $term['Term']['term_id'] : ''; 
         }else{ 
          $data[$i][$table][$field] = (isset($row[$k])) ? $row[$k] : ''; 
         } 
        } 
       } 
      } 
     } 

     $data[$i]['Product']['product_id_supplier'] = $data[$i]['Product']['slug']; 
     $data[$i]['Product']['supplier_id'] = $supplier; 
     $data[$i]['Product']['feedimport_id'] = 1; 

     $i++; 
    } 

    // save the row 
    if (!$this->FeedImport->Product->saveAll($data)) { 
     throw new Exception(); 
    } 

} catch(Exception $e) { 
    $dataSource->rollback($e); 
} 
$dataSource->commit(); 

, 그래서 while 루프에 대한 startline 및 endline을 제공 할 수 있습니다. 하지만 거기에 내가 붙어있어, 나는 fgetcsv를 사용하여 시작과 끝 규칙을 설정하는 방법을 모르겠다. 누군가 나를 도와 줄 수 있습니까?

나는 fseek 등을 사용해 보았지만 그저 끝내지 못했습니다 ... 누군가 나를 도와 줄 수 있습니까?

큰 제품 피드를 가져 오기 위해 LOAD DATA INFILE을 사용하는 것이 좋겠지 만 여러 결합 테이블을 사용하고 여러 테이블에 데이터를 가져 오기 위해 몇 가지 예외를 사용하기 때문에 제대로 작동하지 않을 것이라고 생각합니다. 나쁜.

답변

1

참조 가능한 해결 방법은 데이터를 커밋 카운터 및 데이터 배열을 재설정하고 계속 각 5000 개 레코드에 대한 다음과 같은

while (($row = fgetcsv($handle)) !== false) { 
    if ($i === 5000){ 
     try { 
      if (!$this->FeedImport->Product->saveAll($data)) 
       throw new Exception(); 
     } catch (Exception $e){ 
      $dataSource->rollback($e); 
     } 

     $i = 0; 
     $data = []; 
    } 

    // Code 
} 

될 것이다.

+0

$ dataSource-> commit() 만 추가하면된다. $ i = 0; :) 이제는 5000 레코드를 커밋합니다. 감사합니다! –

1

PHP5.5를 사용하면 새로운 Generator 기능을 활용할 수 있습니다. http://mark-story.com/posts/view/php-generators-a-useful-example

+0

지금 다른 해결책이있을 수 있습니까? 왜냐하면 나는 WAMP로 PHP5.5를 실행하려고했으나, 그저 내 전체 설치를 망쳤다. (그리고 프로젝트는 곧 끝날 필요가있다. :) –