2011-08-25 16 views
1

我寫了一個模塊,可以接收CSV文件並將數據添加到sales_flat_order表(代碼如下)。儘管我對Magento通過數據庫進行交互的懷疑和缺乏知識,但我能夠成功更新表中的必要列。但是,每次運行代碼時,它都會更新這些行,但始終會向表中添加一行額外的所有空值。我已經嘗試打印出原始SQL,但沒有看到任何無關的SQL調用,但它仍在繼續。Magento Zend_Db_Adapter_Abstract ::更新問題

下面是應該幫助解釋我在做什麼的代碼的重要代碼片段。希望這是別人遇到的已知問題,可以指引我朝着正確的方向前進。

首先,這是我的config.xml:

<?xml version="1.0" encoding="UTF-8"?> 
<config> 
    <modules> 
     <VPS_Sorting> 
      <version>0.1.0</version> 
     </VPS_Sorting> 
    </modules> 
    <admin> 
     <routers> 
      <adminhtml> 
       <args> 
        <modules> 
         <sorting after="Mage_Adminhtml">VPS_Sorting</sorting> 
        </modules> 
       </args> 
      </adminhtml> 
     </routers> 
    </admin> 
    <global> 
     <models> 
      <sorting> 
       <class>VPS_Sorting_Model</class> 
       <resourceModel>sorting_mysql4</resourceModel> 
      </sorting> 
      <sorting_mysql4> 
       <class>VPS_Sorting_Model_Mysql4</class> 
<!--     Doesn't need entities when you aren't using your own table!! --> 
      </sorting_mysql4> 
     </models> 
     <blocks> 
      <sorting> 
       <class>VPS_Sorting_Block</class> 
      </sorting> 
     </blocks> 

     <resources> 
      <!-- this section used to install/configure the DB dynamically --> 
      <sorting_setup> 
       <setup> 
        <module>VPS_Sorting</module> 
        <class>VPS_Sorting_Model_Mysql4_Setup</class> 
       </setup> 
       <connection> 
        <use>core_setup</use> 
       </connection> 
      </sorting_setup> 
      <!-- end setup section --> 

      <sorting_write> 
       <connection> 
        <use>core_write</use> 
       </connection> 
      </sorting_write> 
      <sorting_read> 
       <connection> 
        <use>core_read</use> 
       </connection> 
      </sorting_read> 
     </resources> 
    </global> 
    <adminhtml> 
     <acl> 
      ... 
     </acl> 
    </adminhtml> 
</config> 

正如在評論中說,因爲我沒有使用我自己的表(它初始化使用銷售/訂單我沒有提供任何實體資源模型(見一擊)

接下來,我已將此添加到我的的system.xml文件到文件輸入框中添加到配置:

<importcsv translate="label"> 
    <label>Import CSV</label> 
    <comment> 
     <![CDATA[requires 2 columns, 'order_id' and 'real_ship_cost']]> 
    </comment> 
    <frontend_type>import</frontend_type> 
    <backend_model>sorting/import_csv</backend_model> 
    <sort_order>5</sort_order> 
    <show_in_default>1</show_in_default> 
    <show_in_website>1</show_in_website> 
    <show_in_store>1</show_in_store> 
</importcsv> 

下面是的system.xml用於上傳框的backend_model類:

class VPS_Sorting_Model_Import_Csv extends Mage_Core_Model_Config_Data 
{ 
    protected function _construct() 
    { 
     parent::_construct(); 
     $this->_init('sorting/csv'); //initialize the resource model 
    } 


    public function _afterSave() 
    { 
     if($rm = $this->_getResource()) 
      $rm->uploadAndImport($this); 

     else 
      Mage::logException("Failed to load VPS_Sorting Resource Model"); 
    } 
} 

最後,這一切的肉是做所有工作的模型資源類。你可以在這裏看到,我在構造函數中調用_init('sales/order'),這樣我就可以搭載sales_order資源模型,而不必建立單獨的數據庫連接(我假設這沒問題......它正在工作,但讓我知道如果這樣是一個壞主意)

class VPS_Sorting_Model_Mysql4_Csv extends Mage_Core_Model_Mysql4_Abstract 
{ 
    protected $_adapter; 

    protected function _construct() 
    { 
     $this->_init('sales/order', 'entity_id'); 
    } 

    public function uploadAndImport(Varien_Object $object) 
    { 
     $csvFile = $_FILES['groups']['tmp_name']['actions']['fields']['importcsv']['value']; 
     $io = new Varien_Io_File(); 
     $info = pathinfo($csvFile); 
     $io->open(array('path' => $info['dirname'])); 
     $io->streamOpen($info['basename'], 'r'); 

     // check and skip headers 
     $headers = $io->streamReadCsv(); 

     //  return parent::_afterSave(); 
     if ($headers === false || count($headers) < 2 || $headers[0] != 'order_id' || $headers[1] != 'real_ship_cost') 
     { 
      $io->streamClose(); 
      Mage::throwException("Invalid Real Shipping Cost CSV Format. File must contain 2 columns: 'order_id' and 'real_ship_cost'"); 
     } 

     //Varien_Db_Adapter_Pdo_Mysql 
     $this->_adapter = $this->_getWriteAdapter(); 

     $this->_adapter->beginTransaction(); 

     try { 
      $importData = array(); 

      while (false !== ($csvLine = $io->streamReadCsv())) 
      { 
       if (empty($csvLine)) { 
        continue; 
       } 

       $importData[] = array('id' => $csvLine[0], 'rsc' => $csvLine[1]); 

       if (count($importData) == 5000) { 
        $this->_saveImportData($importData); 
        $importData = array(); 
       } 
      } 

      $this->_saveImportData($importData); 

      $io->streamClose(); 
     } catch (Mage_Core_Exception $e) { 
      $this->_adapter->rollback(); 
      $io->streamClose(); 
      Mage::throwException($e->getMessage()); 
     } catch (Exception $e) { 
      $this->_adapter->rollback(); 
      $io->streamClose(); 
      Mage::logException($e); 
      Mage::throwException('An error occurred while importing Real Shipping Cost data.'); 
     } 

     $this->_adapter->commit(); 

     return $this; 
    } 


    protected function _saveImportData($_data) 
    { 
     foreach($_data as $_row) 
     { 
      $this->_adapter->update($this->getMainTable(), array('real_ship_cost' => $_row['rsc']), array('`increment_id` = ?' => $_row['id'])); 
     } 
    } 
} 

我剪了我的很多調試語句簡化它,但要注意的是,如果我呼應$ IMPORTDATA數組的大小總是3從預期是很重要的我的CSV。如果我將日誌記錄添加到Zend_Db_Adapter_Abstract以打印它運行的每個SQL語句,它只會運行3.所以我不知道爲什麼要插入額外的行。

在此先感謝您的幫助!

+0

我啓用了MySql日誌記錄在我的服務器上,並且我發現了有問題的INSERT,但我仍然困惑於它爲什麼這樣做: 112 Query INSERT INTO'sales_flat_order'()VALUES() 112查詢更新'sales_flat_order' SET'real_ship_cost' ='1.23'WHERE(increment_id ='100000001') 112查詢更新'sales_flat_order' SET'real_ship_cost' ='2.34'WHERE增量_id ='100000002') 112查詢更新'sales_flat_order' SET' real_ship_cost' ='3.45'WHERE(increment_id ='100000003') 112查詢提交 – BrianVPS

回答

1

我不是100%確定原因爲什麼會發生這種情況,但我找到了解決辦法。我相信這是由於默認情況下,任何Mage_Core_Model_Config_Data對象都將其值存儲在core_config_data表中。由於我初始化了這個以使用我自己的資源模型,它實際上搭載在sales/order資源模型上,所以令人困惑並且試圖將虛假信息保存到sales/order表中。

要解決它,我做了以下內容:

首先,在構造函數在系統中使用的backend_model類。XML,設置_ dataSaveAllowed標誌

protected function _construct() 
{ 
    parent::_construct(); 
    $this->_init('sorting/csv'); //initialize the resource model 
    $this->_dataSaveAllowed = false; 
} 

下一頁,而是採用_afterSave處理CSV導入,使用_beforeSave_afterSave不叫你的時候不允許保存數據)

這似乎解決了我的問題,但我歡迎任何意見/建議,如果我的方法有缺陷。我仍然對此感到陌生,所以任何經驗豐富的洞察力總是感激:)