Magento Zend_Db_Adapter_Abstract :: проблема обновления - PullRequest
1 голос
/ 26 августа 2011

Я написал модуль, который может взять файл CSV и добавить данные в таблицу sales_flat_order (код ниже). Несмотря на мой скептицизм и отсутствие знаний о взаимодействии с БД через Magento, я смог успешно обновить необходимые столбцы в таблице. Однако каждый раз, когда я запускаю код, он обновляет строки, но всегда добавляет одну дополнительную строку в таблицу со всеми нулевыми значениями. Я попытался распечатать исходный SQL, и я не вижу никаких посторонних вызовов SQL, но он продолжает это делать.

Вот важные фрагменты кода, которые должны помочь объяснить, что я делаю. Надеюсь, это известная проблема, с которой столкнулся кто-то другой, и которая может указать мне правильное направление.

Во-первых, вот мой 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>

Вот класс backend_model, используемый в system.xml для поля загрузки:

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");
    }
}

И наконец, суть всего этого - класс Model Resource, который выполняет всю работу. Здесь вы можете видеть, что я вызываю _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. Поэтому я не знаю, почему вставляется дополнительная строка.

Заранее спасибо за любую помощь!

1 Ответ

1 голос
/ 26 августа 2011

Я не уверен на 100% причина , почему это происходило, но я нашел решение.Я полагаю, что это связано с тем, что по умолчанию любой объект Mage_Core_Model_Config_Data сохраняет свои значения в таблице core_config_data.Так как я инициализировал это, чтобы использовать мою собственную модель ресурсов, которая фактически совмещается с моделью ресурсов sales/order, он запутался и попытался сохранить поддельную информацию в таблицу sales/order.

Чтобы исправить это, я сделалследующее:

Сначала в конструкторе для класса backend_model , используемого в system.xml , установите для флага _ dataSaveAllowed значение false :

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

Далее, вместо использования _afterSave для обработки импорта CSV, используйте _beforeSave ( _afterSave isnне вызывается, когда вы не разрешаете сохранение данных)

Это, похоже, решило мои проблемы, но я приветствую любые комментарии / предложения, если мой метод имеет недостатки.Я все еще новичок в этом, поэтому любое опытное понимание всегда ценится:)

...