Custom Product Attributes, Source Models and Flat Tables

How to add an attribute to product_flat_table

Either one of the following attribute settings is true:

  • backend_typ = 'static'
  • is_filterable > 0
  • used_in_product_listing = 1
  • is_used_for_promo_rules= 1
  • used_for_sort_by = 1

Or you add it manually by observing this event:
catalog_product_flat_prepare_columns

Attribute is not added - source models

If you attribute is still not added it might be, because \Mage_Eav_Model_Entity_Attribute_Abstract::getFlatColumns is called on the attribute, which checks wether a source model exists.

public function getFlatColumns()
{
    // If source model exists - get definition from it
    if ($this->usesSource() && $this->getBackendType() != self::TYPE_STATIC) {
        return $this->getSource()->getFlatColums();
    }
    // ...
}

As you can see, getFlatColums is called on your source model, which default implementation is:

// \Mage_Eav_Model_Entity_Attribute_Source_Abstract::getFlatColums
public function getFlatColums()
{
    return array();
}

Therefore your attribute is not added.

And implementation like this might help:

public function getFlatColums()
{
    $attributeCode = $this->getAttribute()->getAttributeCode();
    $column        = [
        'unsigned' => false,
        'default'  => null,
        'extra'    => null,
    ];

    if (Mage::helper('core')->useDbCompatibleMode()) {
        $column['type']    = 'varchar';
        $column['is_null'] = true;
    } else {
        $column['type']     = Varien_Db_Ddl_Table::TYPE_VARCHAR;
        $column['nullable'] = true;
        $column['comment']  = 'Seals column';
    }

    return [$attributeCode => $column];
}

*Update*

How to fill the field

After the final win that the column is created on the flat tables, it was NULL after reindexing. Something is missing and this is:

\Mage_Eav_Model_Entity_Attribute_Source_Abstract::getFlatUpdateSelect

This method has to return a Zend_Db_Select due to this:

\Mage_Catalog_Model_Resource_Product_Flat_Indexer::updateAttribute
// ...
$select = $attribute->getFlatUpdateSelect($storeId);
if ($select instanceof Varien_Db_Select) {
    if ($productIds !== null) {
        $select->where('e.entity_id IN(?)', $productIds);
    }
}
// ...

An example implementation which works for me:

public function getFlatUpdateSelect($store)
{
    return Mage::getResourceSingleton('eav/entity_attribute')
        ->getFlatUpdateSelect($this->getAttribute(), $store);
}

Price of Bundle Product

We have a template and echoing prices of products. The products are of differenct kind. Simple product, bundle product, etc.

To get the price of a simple product you just call

$_product->getPrice();

When you call this method on a bundle product, it returns 0.00. So how to get the price of a bundle product? Simply call

$_product->getData('price');

To be honest I'm not sure, what price this is. We misuse bundle products as grouped products, that means we group products. No option to change the quantity or the "content" of the product. Because of this, our bundle product has only one price, not many ones, depending on the combination of the options.

One small note on this: There is a attribute on the bundle product object. It was something like price_calculated or calculated_price. I can't remember the name and didn't find it fast to double check.