Magento – Saving Custom EAV Model Attributes

attributesdatabaseeav

I have a custom EAV model that uses custom tables for comments that can be set on either products or categories. I have created an admin for these using the standard EAV admin form.

In my controller, I have a save action:

public function saveAction()
{
    if ($data = $this->getRequest()->getPost()) {
        try {
            $model = Mage::getModel('module/comment');
            $model->setData($data)->setId($this->getRequest()->getParam('id'));
            $model->save();

            $this->_getSession()->addSuccess(
                Mage::helper('module')->__('The comment has been saved.'));

            $this->_redirect('*/*/edit',
                array('id' => $this->getRequest()->getParam('id')));
        }
        catch (Exception $e) {
            Mage::logException($e);
            $this->_getSession()->addError(Mage::helper('module')->__('There was an error saving the comment'));
        }
    }
    $this->_redirect('*/*/index');
}

When I save the form with a new comment, the grid page shows the new comment. But, when I look in the database with the following query:

SELECT * FROM eav_comment_text WHERE entity_id = 1;

I see the following:

+----------+----------------+--------------+----------+-----------+-------------------------+
| value_id | entity_type_id | attribute_id | store_id | entity_id | value                   |
+----------+----------------+--------------+----------+-----------+-------------------------+
|        1 |             31 |          964 |        0 |         1 | test                    |
|        4 |             31 |          964 |        0 |         1 | test adding another one |
+----------+----------------+--------------+----------+-----------+-------------------------+

Can anyone explain why (a) Magento does not replace the existing value and (b) how Magento knows which one to show in the grid?

Best Answer

TL;DR: you need a unique index on the following combination of columns: entity_id,attribute_id,store_id.

Long answer:

On an EAV entity (let's take products for example) your table could never look like that.
You have 2 records for the same combination of attribute_id | store_id | entity_id.
On the product tables (catalog_product_entity_varchar for example but it's the same for _int and others) there is a unique constraint on these 3 columns.

UNIQUE KEY `UNQ_CAT_PRD_ENTT_VCHR_ENTT_ID_ATTR_ID_STORE_ID` (`entity_id`,`attribute_id`,`store_id`),  

This is created in the install script (see install-1.6.0.0.php)

->addIndex(
    $installer->getIdxName(
        array('catalog/product', 'varchar'),
        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))

And when saving an attribute value (insert or update) a call to the method insertOnDuplicate is made.
This method tries to insert the values you provide to it and if there is a unique key duplicate it just updates the values you specify. In the case of the EAV tables only the value field is updated.
Since you don't have that unique constraint on the table it just inserts an other row.
Try adding that constraint and I have a feeling the problem will go away.

Related Topic