当saveAction()时,Magento自定义模块与数据库中的EAV重复属性行

时间:2013-10-13 16:44:36

标签: magento module save duplicates entity-attribute-value

我有一个带EAV结构的自定义Magento模块。它可以创建,编辑,删除和列出项目。

当我编辑并保存项目时,属性值不会被数据库中的新值替换。在管理员上,我看到了新值,但在数据库中也存在旧值。

我看作管理员用户:
- 项目编辑
- 从测试1改变名称t t测试2
- 保存成功
- 现在,该项目的名称为Test 2

我在数据库中看到的内容:
- value_id,entity_type_id,attribute_id,store_id,entity_id,value
- 旧行:5,31,961,0,5,测试1
- 新行:6,31,961,0,5,测试2

代码中:

public function saveAction()
{
    if ($postData = $this->getRequest()->getPost()) {
        $model = Mage::getSingleton('mynamespace/model');

        $model->setData($postData);

        if ($this->getRequest()->getParam('id')) {
            $model->setId($this->getRequest()->getParam('id'));
        }

        try {
            $model->save();

            Mage::getSingleton('adminhtml/session')->addSuccess($this->__('Item has been saved.'));
            $this->_redirect('*/*/');

            return;
        }
        catch (Mage_Core_Exception $e) {
            Mage::getSingleton('adminhtml/session')->addError($e->getMessage());
        }
        catch (Exception $e) {
            Mage::getSingleton('adminhtml/session')->addError($this->__('An error occurred while saving this item.'));
        }

        $this->_redirectReferer();
    }
}

我第一次有一排。保存后我有两排,再保存后我有三排... 为什么setData()或setName()函数不能覆盖/更新旧行?为什么要创建新行?我该如何解决?

安装程序文件:

$installer = $this;
$installer->startSetup();

$eavTableName = 'loremipsum/lorem';

$installer->addEntityType(
    'loremipsum_lorem', array(
        'entity_model'    => $eavTableName,
        'table'           => $eavTableName
    )
);

$installer->createEntityTables(
    $this->getTable('loremipsum/lorem')
)->addIndex(
    $this->getIdxName(
        $eavTableName,
        array('entity_id', 'attribute_id', 'store_id'),
        Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
    ),
    array('entity_id', 'attribute_id', 'store_id'),
    array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)
);

$this->addAttribute('loremipsum_lorem', 'name', array(
    'type'              => 'varchar',
    'label'             => 'Name',
    'input'             => 'text',
    'class'             => '',
    'backend'           => '',
    'frontend'          => '',
    'source'            => '',
    'required'          => true,
    'user_defined'      => true,
    'default'           => '',
    'unique'            => false
));

$installer->endSetup();

2 个答案:

答案 0 :(得分:2)

看起来问题与缺少唯一索引-_-

有关

尝试通过以下列添加一个唯一索引到您的实体表(_int,_varchar,_decimal,....)

entity_id, attribute_id, store_id

在我添加这些之后,它为我工作

如果要修复安装脚本: 您需要创建/更新Setup Class

问题出在Mage_Eav_Model_Entity_Setup::createEntityTables函数中,它缺少唯一索引。将该功能复制到您的安装程序类中并添加

            ->addIndex(
                $this->getIdxName(
                    $eavTableName,
                    array('entity_id', 'attribute_id', 'store_id'),
                    Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
                ),
                array('entity_id', 'attribute_id', 'store_id'),
                array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE));

进入eav_tables的创建声明 之后,创建eav表的foreach循环应如下所示:

    /**
     * Create table array($baseTableName, $type)
     */
    foreach ($types as $type => $fieldType) {
        $eavTableName = array($baseTableName, $type);

        $eavTable = $connection->newTable($this->getTable($eavTableName));
        $eavTable
            ->addColumn('value_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
                'identity'  => true,
                'nullable'  => false,
                'primary'   => true,
                'unsigned'  => true,
            ), 'Value Id')
            ->addColumn('entity_type_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
                'unsigned'  => true,
                'nullable'  => false,
                'default'   => '0',
            ), 'Entity Type Id')
            ->addColumn('attribute_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
                'unsigned'  => true,
                'nullable'  => false,
                'default'   => '0',
            ), 'Attribute Id')
            ->addColumn('store_id', Varien_Db_Ddl_Table::TYPE_SMALLINT, null, array(
                'unsigned'  => true,
                'nullable'  => false,
                'default'   => '0',
            ), 'Store Id')
            ->addColumn('entity_id', Varien_Db_Ddl_Table::TYPE_INTEGER, null, array(
                'unsigned'  => true,
                'nullable'  => false,
                'default'   => '0',
            ), 'Entity Id')
            ->addColumn('value', $fieldType[0], $fieldType[1], array(
                'nullable'  => false,
            ), 'Attribute Value')
            ->addIndex($this->getIdxName($eavTableName, array('entity_type_id')),
                array('entity_type_id'))
            ->addIndex($this->getIdxName($eavTableName, array('attribute_id')),
                array('attribute_id'))
            ->addIndex($this->getIdxName($eavTableName, array('store_id')),
                array('store_id'))
            ->addIndex($this->getIdxName($eavTableName, array('entity_id')),
                array('entity_id'))
            ->addIndex(
                $this->getIdxName(
                    $eavTableName,
                    array('entity_id', 'attribute_id', 'store_id'),
                    Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
                ),
                array('entity_id', 'attribute_id', 'store_id'),
                array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE));
        if ($type !== 'text') {
            $eavTable->addIndex($this->getIdxName($eavTableName, array('attribute_id', 'value')),
                array('attribute_id', 'value'));
            $eavTable->addIndex($this->getIdxName($eavTableName, array('entity_type_id', 'value')),
                array('entity_type_id', 'value'));
        }

        $eavTable
            ->addForeignKey($this->getFkName($eavTableName, 'entity_id', $baseTableName, 'entity_id'),
                'entity_id', $this->getTable($baseTableName), 'entity_id',
                Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
            ->addForeignKey($this->getFkName($eavTableName, 'entity_type_id', 'eav/entity_type', 'entity_type_id'),
                'entity_type_id', $this->getTable('eav/entity_type'), 'entity_type_id',
                Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
            ->addForeignKey($this->getFkName($eavTableName, 'store_id', 'core/store', 'store_id'),
                'store_id', $this->getTable('core/store'), 'store_id',
                Varien_Db_Ddl_Table::ACTION_CASCADE, Varien_Db_Ddl_Table::ACTION_CASCADE)
            ->setComment('Eav Entity Value Table');

        $tables[$this->getTable($eavTableName)] = $eavTable;
    }

如果您已经创建了该实体并且您不想重新安装/删除表格,请尝试以下未经测试

//your entity types
$entityTypes = array('datetime', 'decimal', 'int', 'text', 'varchar');
foreach($entityTypes AS $type){
    $connection->addIndex(
        $this->getTable('loremipsum/lorem') . '_' . $type,
        $installer->getIdxName(
            $eavTableName,
            array('entity_id', 'attribute_id', 'store_id'),
            Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE
        ),
        array('entity_id', 'attribute_id', 'store_id'),
        array('type' => Varien_Db_Adapter_Interface::INDEX_TYPE_UNIQUE)
    );
}

答案 1 :(得分:2)

尝试在资源模型中覆盖_updateAttribute方法

protected function _updateAttribute($object, $attribute, $valueId, $value)
{
    $table = $attribute->getBackend()->getTable();
    if (!isset($this->_attributeValuesToSave[$table])) {
        $this->_attributeValuesToSave[$table] = array();
    }

    $entityIdField = $attribute->getBackend()->getEntityIdField();

    $data   = array(
        'entity_type_id'    => $object->getEntityTypeId(),
        $entityIdField      => $object->getId(),
        'attribute_id'      => $attribute->getId(),
        'value'             => $this->_prepareValueForSave($value, $attribute)
    );
    if ($valueId)
    {
        $data['value_id'] = $valueId;
    }

    $this->_attributeValuesToSave[$table][] = $data;

    return $this;
}

如果找到value_id数组,则$data仅添加{{1}}。这解决了这个问题。 此解决方案也可在以下位置找到:http://code007.wordpress.com/2014/03/24/magento-rows-are-not-updated-in-custom-eav-model-tables/