我有一个带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();
答案 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/