Day: June 23, 2010

  • Magento meta keywords field name inconsistent

    I don’t know whether Magento did this on purpose. Both of category page and product page have a meta keywords attribute. Because meta keywords attribute of category or product belongs to EAV system, it has two entries in eav_attribute table, one for catalog_category (entity_type_id = 3) and one for catalog_product (entity_type_id = 4). However, if you look closely at attribute_code, you will find –

    • for category, the code is meta_keywords
    • for product, the code is meta_keyword

    The cms_page also has meta keywords, but it does not belongs to EAV system. The field name is meta_keywords.

    In summary, you won’t retrieve any meta keywords of a product if you write code like this:

    Mage::getModel('catalog/product')->load($productId)->getData('meta_keywords');
    
    
  • Magento code snippet

    Magento provide a beautiful GUI, which let you setup or change nearly everything. However, occasionally you prefer do it with php code. Here are a collection of codes for various functionalities. I will keep editing this post to add new methods.

    Read if a product attribute is “Use Default Value” in a Store View:

    Assume the storeview ID is $storeId, the product attribute code is $attributeCode;

    $result = Mage::getModel(‘catalog/product’)->setStoreId($storeId)->getAttributeDefaultValue($attributeCode);

    $result === false when the attribute IS “Use Default Value”;

    $result === Mage::getModel(‘catalog/product’)->setStoreId(0)->getAttributeDefaultValue($attributeCode) when the attribute HAS storeview specific value.

    Please note even if the attribute is “Yes/No” choice type, the attribute value is 1 or 0. So there is no conflict – when getAttributeDefaultValue returns false means “Use Default Value”; when it returns 0 means “default value is No”.

    Read storeview specific value to a product attribute:

    public function getAttributeOptionValue($optionId, $storeId = 0, $attributeId = null)
    {
    	$valuesCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
    		->setStoreFilter($storeId, false)
    		->addFieldToFilter('main_table.option_id', $optionId)
    		->setAttributeFilter($attributeId);
            return $valuesCollection->getFirstItem()->getValue();
    }
    

    CRUD manipulation on entity attributes, such as product attribute

    All need to do is construct an array in the right structure, add to the attribute, and save. Do not operate on ‘eav/entity_attribute_option’ directly. It won’t work because relationship between table eav_attribute_option and eav_attribute_option_value is not set in this model.

    Add options to attribute

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $data = array(
    	'option' => array(
    		'value' => array(
    			$optionId => array(
    				$storeId => $value
    			)
    		)
    	)
    );
    $attribute->addData($data)->save();
    

    Bear in mind, as this is to add a new option, you do not need to specify an actual $optionId. It can be any string which, if convert to number, must be 0. If $optionId’s numeric value is positive, and if that option does not exist or does not belong to the $attribute, it will throw exception like:

    SQLSTATE[23000]: Integrity constraint violation: 1452 Cannot add or update a child row: a foreign key constraint fails.

    You can construct an array with more than one option ID’s and store ID’s inside to add multiple options or give option values to multiple stores at a time.

    Read options

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $optionCollection = Mage::getResourceModel('eav/entity_attribute_option_collection')
    	->setStoreFilter($storeId, false)
    	->setAttributeFilter($attribute->getId());
    foreach ($optionCollection as $option) {
    	echo $option->getValue();
    }
    

    The code is straight forward. I did not find another way retrieving options. I tried
    $attribute->getOptions() and $attribute->getOption(). Neither worked.

    Delete options

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $data = array(
    	'option' => array(
    		'value' => array(
    			$optionId => ''
    		),
    		'delete' => array(
    			$optionId => 1
    		)
    	)
    );
    $attribute->addData($data)->save();
    

    The tricky thing is: the $optionId to delete must exist in both ‘value’ and ‘delete’, although the value itself is not critical (because it will be deleted).

    Update options

    $attribute = Mage::getModel('eav/entity_attribute')->loadByCode('catalog_product', $attributeCode);
    $data = array(
    	'option' => array(
    		'value' => array(
    			$optionId => array(
    				$storeId => $value
    			)
    		)
    	)
    );
    $attribute->addData($data)->save();
    

    It is the same code as adding options. The difference is in $optionId. You need work out the existing option ID.

    CRUD manipulation does not need to construct $data with the complete list of existing options. Any options not in $data is untouched.