Working with Magento product attributes programmatically

Posted by Joaquín Ruiz on 5th April 2016

Working with Magento product attributes programmatically

Magento Product attributes

Magento Product attributes

Magento Product attributes are one of the most powerful features in Magento. You can create and customize attributes in Magento to manage complex arrays of product data.

There are two kinds of attributes in Magento: System attributes and Custom attributes. System attributes are the ones that Magento includes by default. They are the necessary attributes that we need to begin our Magento eCommerce, like name, price, sku number, etc… The Custom attributes, on the other hand, are attributes created by the Store Owner, and will not necessarily be included in every Attribute set.

Sometimes when creating custom importers, synchronizing products… you face a lot of issues related to Magento Product attributes. This guide is meant to help Magento 1.x developers to work with attributes, both using Magento code and querying directly on the database.

The Attribute (EAV) model

In Magento, all the models inherit from the ‘Mage_Core_Model_Abstract / Varien_Object‘ chain. What makes something either a simple Model or an EAV model is its Model Resource. EAV models have a resource that inherits from ‘Mage_Eav_Model_Entity_Abstract’.

The EAV Model is one of the most complex part of Magento. But it is really useful if you need a data model that will have flexible attributes which can be dynamically added. That is the case of Magento attributes. Don’t worry about this right now, you’ll understand it at the end of this guide. 🙂

NOTE that in some cases using the EAV Model is not the fastest solution, that is the reason that Magento offers Flat Tables.

Flat tables in Magento

This is a basic way to speed up the product collection. To enable it, go to Magento admin section and click on: System -> Config -> Catalog and Frontend.

product_flat_collection

When flat tables are enabled, Magento will continue to store a product’s attributes as EAV so the store must be re-indexed in order for changes to appear on the front-end. Every store in Magento has it’s own flat table of products. If flat is enabled in Magento, the product collection will use resource: ‘catalog/product_flat’, php class “Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Flat” without EAV database structure. SQL queries will be simplier, faster and you will have better performance on product listing.

You can include your product attribute in the flat catalog, you just need to enable the ‘Used in product listing’ setting in Catalog > Attributes > Manage Attributes. This way, you’ll increase the performance of your catalog collections.

Using the eav/entity_attribute Model

To get the Attribute model by the attribute_code using the entity_attribute Model, you have to provide the entity_type (‘catalog_product’ for attribute products) because you can have same attribute_code for different entities.

$attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', 'custom_attribute_code');

Magento offers by default 9 input types for product attributes:

  • text field
  • text area
  • date
  • yes/no
  • multiple select
  • dropdown
  • price
  • media image
  • fixed product tax

Each attribute type have different options and features, so you should retrieve the Product attribute type by calling the method:

$attribute_type = $attribute->getFrontendInput();

Often, you only need to differentiate if the attribute is limited to a set amount of options, or can be any value. This is important, because if you are retrieving an attribute from a product that can be any value, you’ll get the value directly, but if the attribute is limited to a set amount of options, you’ll end up with a number id.

Therefore, you can differentiate the kind of input (limited-options, direct value) with the method:

if ($attribute->usesSource()) {} 

To retrieve the value of an attribute that is limited to a set amount of options, you have to use the Source Model of the attribute. That can be easily done by using these methods:

$attribute_id = $attribute->getSource()->getOptionId('attribute_value');
$attribute_value = $attribute->getSource()->getOptionText('attribute_id');

And in case you want to list all the options as an array:

$options_array = $attribute->getSource()->getAllOptions();

You can also customize the Source of an Attribute, and link it, for example to a custom entity, by extending the class ‘Mage_Eav_Model_Entity_Attribute_Source_Abstract’ and overwrite for instance the method ‘getAllOptions’, adding your custom Entity fields to the method. This way you could create an Entity ‘team’, and add to that entity fields like ‘image_shield’, ‘date_create’, ‘description’… and create a Custom Magento Product Attribute called ‘team’ as well, and link the Source of that Attribute to the entity ‘team’ Model.

Using the Product Resource Model

You can also get all the Magento Product attributes information using the Resource Model of the Product as I show next:

$attribute = $product->getResource()->getAttribute('attribute_code');

This can be really helpful in case your attribute source is misconfigured.

Source model "" not found for attribute "attribute_code"

Using the Product Model you can get directly the attribute values of your product. This small code can be really useful to retrieve any kind of product attributes.

switch ($inputType) {
    case 'multiselect':
    case 'select':
    case 'dropdown':
        $value = $product->getAttributeText($attribute_code);
        if (is_array($value)) {
            $value = implode(', ', $value);
        }
        break;
    default:
        $value = $product->getData($attribute_code);
        break;
}

Querying directly to the Database

Sometimes you need to query directly to the database to create reports or directly to improve the performance of some parts of your code. If you query directly to flat tables, you’ll end up with problems while reindexing your Magento store.

For text input Magento Product attributes you can use this simple query:


SELECT 'whatever' FROM catalog_product_entity AS entities
LEFT JOIN eav_attribute AS attributes
    ON entities.entity_type_id = attributes.entity_type_id 
    AND attributes.attribute_code = 'attribute_code'
LEFT JOIN catalog_product_entity_varchar AS attribute_varchar
    ON entities.entity_id = attribute_varchar.entity_id 
    AND attributes.attribute_id = attribute_varchar.attribute_id

And to retrieve the value of limited-option Magento Product attributes you can use this query:


SELECT 'whatever' FROM catalog_product_entity AS entities
LEFT JOIN eav_attribute AS attributes
    ON entities.entity_type_id = attributes.entity_type_id 
    AND attributes.attribute_code = 'attribute_code'
LEFT JOIN catalog_product_entity_int AS attribute_int
    ON entities.entity_id = attribute_int.entity_id 
    AND attributes.attribute_id =attribute_int.attribute_id
LEFT JOIN eav_attribute_option_value AS attribute_value
    ON attribute_int.value = attribute_value.option_id

The catalog_product_entity is the main table/model for products. ENTITY

The eav_attribute is the main table/model for attributes. ENTITY

The attribute_TYPE is the attribute table. ATTRIBUTE
Note that the TYPE can be taken from the column ‘backend_type’ of the entity table ‘eav_attribute’.

The eav_attribute_option_value table is the values table. VALUE

There you go! the EAV model 😉

eav

Bonus: Create a product Attribute programmatically

When developing Magento modules, you’ll often find yourself in the situation where you have to create an specific product attribute. As you may know, you can use an installer script to create product attributes. On this case, we will use an install script to create a product attribute.


$installer = $this;

$installer->startSetup();

$installer->addAttribute('catalog_product', 'attribute_code', array(
 'type' => 'int',
 'backend' => '',
 'frontend' => '',
 'label' => 'attribute_label',
 'input' => 'text',
 'class' => '',
 'source' => '',
 'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_GLOBAL,
 'visible' => false,
 'required' => false,
 'user_defined' => false,
 'default' => '',
 'searchable' => false,
 'filterable' => false,
 'comparable' => false,
 'visible_on_front' => false,
 'unique' => false,
 'apply_to' => '',
 'is_configurable' => false
));

$installer->endSetup();

Conclusions

EAV and Flat tables : Activating the flat tables is a big boost in performance, because instead of a lot of joins to get the product attributes, Magento only reads from one table. It has been the way to speed up data access from EAV since EAV was conceived.
Note: To ensure that the changes take place on the front-end, reindex the appropriate flat data like so:

cd {magento_root}/shell
php indexer.php --reindex catalog_product_flat
php indexer.php --reindex catalog_category_flat

Attributes Integrity : When working with product attributes, you can specify custom Sources for your attribute. Make sure you follow the Magento standards or you will end up with errors like:

Source model "" not found for attribute "attribute_code"

And these problems could damage some Magento features like import/export.

Hope this guide and code examples help someone.

Your feedback and comments are very welcomed!




About the author:

Joaquín Ruiz is a Computer Engineer, Senior PHP Developer and Magento Certified Developer. Joki has more than 7 years of experience working with multiple PHP frameworks. He knows Magento, WordPress, Laravel, Yii.. like the back of his hand ;)


  • Michael Gomes

    Very good, I have several scripts that will apply in this way, thanks

  • Wuzeko

    Great one dude, It was helpful.