I have built an observer event that fires on catalog_product_save_before to parse the price of associated products and set another attribute to yes/no based on the result:

public function catalog_product_save_before($observer)
    $onsale = false;
    $product = $observer->getProduct();     
    if ($product->getTypeId() == 'grouped'){
        $associatedProducts = $product->getTypeInstance(true)->getAssociatedProducts($product);
    }  else if ($product->getTypeId() == 'configurable') {
        $associatedProducts = $product->getTypeInstance(true)->getUsedProducts($product);
    if (isset($associatedProducts)) {
        foreach ($associatedProducts as $simple) {
            if ($simple->getPrice() > $simple->getSpecialPrice()) {
                $onsale = true;
                //no point wasting time if we find something, break the loop and return a true
        //set attribute to true or false depending on above. 

My config xml:

<?xml version="1.0"?>

The above works fine when i save the product in the backend as normal.

However, I need this attribute to be calculated for all products, and then whenever they change / the price changes.

The event is not fired for all products during a complete reindex, even when I change the attributes of all products using the mass modification tool on the product grid.

Is there something else I need to do to ensure this event will fire whenever the product changed?

  • Please post the code code of your config.xml Jun 17, 2015 at 4:26
  • Added my config to the question
    – Ucinorn
    Jun 17, 2015 at 4:29

1 Answer 1


The event you're observing, catalog_product_save_before is not all-encompassing. For example, you mentioned that it doesn't trigger on mass-action changes to products. If you look at the code around this activity, you'll see that no product models are actually saved.

See Mage_Adminhtml_Catalog_ProductController::massStatusAction and notice:

            ->updateAttributes($productIds, array('status' => $status), $storeId);

If you follow that method to its class, Mage_Catalog_Model_Product_Action::updateAttributes, you would see that no product models are loaded/saved here. Instead, a less intensive route is taken.

But the good news is that there you would also see other events triggered: catalog_product_attribute_update_[before|after].

In the same way, the indexing processes do not interact with product models as you might expect. See Mage_Index_Model_Indexer::processEntityAction for example, and you can find that you might be able to observe the [start|end]_process_event_catalog_product_[mass_action|save|delete|reindex] events.

I think it comes down to observing more events, or else re-thinking how you want to manage product changes.

  • Ah, I see. So this means that if i hook my method to catalog_product_attribute_update_before, then my method will activate for the product that changed, regardless of what attribute changed.
    – Ucinorn
    Jun 17, 2015 at 4:48
  • For massStatusAction, yes, but this method is specifically for the status attribute, so you will know what to look for on your products if detecting changes. If you're talking about mass attribute updates, that's handled through a different controller and action (eg: Mage_Adminhtml_Catalog_Product_Action_AttributeController::saveAction) but it ultimately uses the same product action model to update the attributes (and so also triggers the same events). Jun 17, 2015 at 4:58
  • Thanks for your help, Rick, but still not sure if i need a rewrite or if my indexer is broken. Everything I've read tells me that a full reindex should call the save_before event on catalog_model but its not happening for me.
    – Ucinorn
    Jun 17, 2015 at 5:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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