6

I've tried removing an eav_entity_attribute using this code:

$entAttr = Mage::getModel('eav/entity_attribute')->getCollection()
        ->addFieldToFilter('attribute_set_id',$set->getId())
        ->addFieldToFilter('attribute_id',$attId)->getFirstItem();


    $entAttr->delete();

but it doesn't work. I receive this error: Column not found: 1054 Unknown column 'attribute_set_id' in 'where clause''

How can I delete an eav_entity_attribute this way?

16

The short version

Mage::getModel('catalog/product_attribute_set_api')->attributeRemove($attId, $set->getId());

Your error message isn't popping up due to your delete method call, it's popping up due to your collection use. For reasons lost to the mystery and smog of Los Angeles, the eav/entity_attribute resource model class is initialized with the eav/attribute resource string.

#File: app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php
protected function _construct()
{
    $this->_init('eav/attribute', 'attribute_id');
}

This means the following collection

$collection = Mage::getModel('eav/entity_attribute')->getCollection();

Actually queries the eav_attribute table.

$sql = $collection->getSelect()->__toString();
echo($sql);

//prints SELECT `main_table`.* FROM `eav_attribute` AS `main_table`

@DavidTay was actually on the right track. Whenever you're in doubt about how to do something in Magento, look at how the core team themselves did it. However, while looking at the admin console code for this will lead you to a method for removing your attribute from a attribute set, it's even better to look at API implementation code. This API code has an implicit promise of doing things in a stable way, where a lot of the early admin console code shows the scars of having been developed rapidly.

If you take a look at the removeAttribute implementation for the attribute set api class, you'll find your answer.

#File: app/code/core/Mage/Catalog/Model/Product/Attribute/Set/Api.php
public function attributeRemove($attributeId, $attributeSetId)
{
    // check if attribute with requested id exists
    /** @var $attribute Mage_Eav_Model_Entity_Attribute */
    $attribute = Mage::getModel('eav/entity_attribute')->load($attributeId);
    if (!$attribute->getId()) {
        $this->_fault('invalid_attribute_id');
    }
    // check if attribute set with requested id exists
    /** @var $attributeSet Mage_Eav_Model_Entity_Attribute_Set */
    $attributeSet = Mage::getModel('eav/entity_attribute_set')->load($attributeSetId);
    if (!$attributeSet->getId()) {
        $this->_fault('invalid_attribute_set_id');
    }
    // check if attribute is in set
    $attribute->setAttributeSetId($attributeSet->getId())->loadEntityAttributeIdBySet();
    if (!$attribute->getEntityAttributeId()) {
        $this->_fault('attribute_is_not_in_set');
    }
    try {
        // delete record from eav_entity_attribute
        // using entity_attribute_id loaded by loadEntityAttributeIdBySet()
        $attribute->deleteEntity();
    } catch (Exception $e) {
        $this->_fault('remove_attribute_error', $e->getMessage());
    }

    return true;
}

Parsing this code out from it's API error checking — first you load an eav/entity_attribute model by it's attribute id.

$attribute = Mage::getModel('eav/entity_attribute')->load($attributeId); 

Remember, for reasons we don't know, this actually loads data from the eav_attribute table because of what's in the resource model _construct.

Next, we set the attribute set id on the eav/entity_attribute model.

$attribute->setAttributeSetId($attributeSet->getId())->loadEntityAttributeIdBySet();

Then, we call the object's deleteEntity method, which actually removes the data from the correct table (eav_entity_attribute)

// delete record from eav_entity_attribute
// using entity_attribute_id loaded by loadEntityAttributeIdBySet()
$attribute->deleteEntity();

If you trace the deleteEntity method to the model

#File: app/code/core/Mage/Eav/Model/Entity/Attribute.php
public function deleteEntity()
{
    return $this->_getResource()->deleteEntity($this);
}

and then to the resource model

#File: app/code/core/Mage/Eav/Model/Resource/Entity/Attribute.php
public function deleteEntity(Mage_Core_Model_Abstract $object)
{
    if (!$object->getEntityAttributeId()) {
        return $this;
    }

    $this->_getWriteAdapter()->delete($this->getTable('eav/entity_attribute'), array(
        'entity_attribute_id = ?' => $object->getEntityAttributeId()
    ));

    return $this;
}

you can see that ultimately, Magento is using a DELETE query with the write adapter to remove the row.

Rather than do this yourself every-time, you can just call the API method directly. Not via XML-RPC or SOAP, but by manually instantiating the API implementation class

Mage::getModel('catalog/product_attribute_set_api')->attributeRemove($attributeId, $attributeSetId);
  • I used this in quick script with Mage_Eav_Model_Entity_Setup and it worked a treat. However to completely nail the attribute, I also had to run $setup->removeAttribute($attributeSetId, $attributeId); to get rid of it from eav/attribute too. – PanPipes Jan 15 '16 at 15:55
2

In the admin, under Catalog -> Attributes -> Manage Attribute Sets, take a look at how attributes are added and removed from sets. Note that you are in the catalog section, so that the entity type id for this section is 4 ( for catalog product).

When you move an attribute in or out of a group and then save, the back end controller that handles the action is Mage_Adminhtml_Catalog_Product_SetController. Go to the saveAction method there. Dump some variables to see how the core code is saving attribute sets (and in general, learn how Magento works). In Chrome, I open up developer tools and watch the ajax network activity; dumped data shows in the response tab.

Basically, the action is expecting a post array of data for saving to the table, including attributes in groups: [[ attribute_id, group_id, sort_order,...],...]. Where this data is prepped for saving to the database is in Mage_Eav_Model_Entity_Attribute_Set.

I realize this is not exactly the answer you are expecting, I thought that you should try to understand how the back end works to avoid data corruption. Good luck.

  • This really doesn't answer the question. I understand what you're trying to do but that really isn't the point of sites like this. If every answer was to do more research yourself, this site would be pointless – jstrez77 Aug 9 '13 at 1:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.