2011-08-25 45 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不叫你的时候不允许保存数据)

这似乎解决了我的问题,但我欢迎任何意见/建议,如果我的方法有缺陷。我仍然对此感到陌生,所以任何经验丰富的洞察力总是感激:)