Hiding “Out of Stock” Items in Magento
Updated 7/14/09
This module has been replaced with one that correctly updates the layered navigation counts. See the new version here.
Updated 7/3/09
The in-stock-only module now works properly when multiple websites are in use.
Updated 6/26/09
The in-stock-only module now works with configurable products.
Magento has several criteria for determining if an item should be visible in the store, but one of these is not whether or not the item is in stock. Magento can manage your stock and will set your stock status to “Out of Stock” for you, but what if you want these out of stock items to be hidden from the store.. automatically? Also, in my case I do not want to “disable” the item because the inventory management system will then ignore it. Turns out this was much more difficult to figure out than I expected it to be but the end solution was quite simple.
To hide all out of stock items from Magento’s storefront we are going to create a local module and call it “Lucky_InStockOnly”. This will be a very simple module, so get ready to copy and paste.
Every module needs a config file. Ours is very basic, here it is:
app/code/local/Lucky/InStockOnly/etc/config.xml
<?xml version="1.0"?> <config> <global> <models> <lucky_instockonly> <class>Lucky_InStockOnly_Model</class> </lucky_instockonly> </models> </global> <frontend> <events> <catalog_block_product_list_collection> <observers> <lucky_instockonly_list> <type>singleton</type> <class>lucky_instockonly/observer</class> <method>addInStockOnlyFilter</method> </lucky_instockonly_list> </observers> </catalog_block_product_list_collection> </events> </frontend> </config>
As you can see, we declare an event for the frontend that observes the “catalog_block_product_list_collection” event which is dispatched in Mage_Catalog_Block_Product_List
in the _beforeToHtml()
method. This _beforeToHtml method is called before the corresponding template code is loaded, and the next line after the dispatchEvent loads the collection at which point it is too late to add any further filters, so we’re just in time.
Next, we add the observer code:
app/code/local/Lucky/InStockOnly/Model/Observer.php
<?php class Lucky_InStockOnly_Model_Observer { /** * Observes the catalog_block_product_list_collection event */ public function addInStockOnlyFilter($observer){ $observer->getEvent()->getCollection() ->joinField('stock_status','cataloginventory/stock_status','stock_status', 'product_id=entity_id', array( 'stock_status' => Mage_CatalogInventory_Model_Stock_Status::STATUS_IN_STOCK, 'website_id' => Mage::app()->getWebsite()->getWebsiteId(), )) ; } }
That’s it! That’s it? Like all things Magento, easy for a veteran, not so easy for anyone else; hence, this blog post. All that is left is to enable our module and we’re off!
app/etc/modules/Lucky_InStockOnly.xml
<config> <modules> <Lucky_InStockOnly> <active>true</active> <codePool>local</codePool> </Lucky_InStockOnly> </modules> </config>
Last thing, you need to refresh your configuration cache so Magento will notice the new module. In the admin backend you can do that under System > Cache Management.
Enjoy!