2013-11-27 69 views
0

我試圖將一個大的CSV文件(約23.000行)導入到我的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一個和底線。但是我遇到了困難,我不知道如何使用fgetcsv設置開始和結束規則。有人能幫助我嗎?

我試過使用fseek等,但我只是無法完成它......有人可以幫我在這裏嗎?

我考慮使用LOAD DATA INFILE來導入那些大的產品供給,但我認爲這不會很好地工作,因爲我使用多個連接表和一些例外情況將數據導入到多個表中......所以,壞。

回答

1

可能的解決方法將是以下

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 
} 

對於每5000條記錄它會提交數據時,重置計數器和數據陣列和繼續。

+0

這很好,只需要添加$ dataSource-> commit();高於$ i = 0; :)現在它確實承諾每5000條記錄,謝謝! –