Search code examples
magentomodulesaveduplicatesentity-attribute-value

Magento custom module with EAV duplicate attribute rows in database when saveAction()


I have a custom Magento module with EAV structure. It can create, edit, delete and listing items.

When I edit and save an item the attribute value doesn't replace by new value in the database. On the admin, I see the new value but in the database the old value exist too.

What I see as admin user:
- Item editing
- Changing Name from Test 1 t Test 2
- Save is successful
- Now, the item's name is Test 2

What I see in the database:
- value_id, entity_type_id, attribute_id, store_id, entity_id, value
- Old row: 5, 31, 961, 0, 5, Test 1
- New row: 6, 31, 961, 0, 5, Test 2

In the code:

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

First time I have one row. After save I have two rows, after save again I have three... Why setData() or setName() functions can not overwrite/update the old rows? Why does it create new rows? How can I fix it?

Installer file:

$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();

Solution

  • Try overriding in your resource model the _updateAttribute method

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

    Only the value_id is added to the $data array if one found. That solves the problem. This solution can be also found at: http://code007.wordpress.com/2014/03/24/magento-rows-are-not-updated-in-custom-eav-model-tables/