I need to push out of stock products to the end of catalog list

Please guide me how to solve this problem, or that file to dig

so far I found Toolbar.php, and working around it

closed as off-topic by SR_Magento, brentwpeterson, Kristof at Fooman, Rajeev K Tomy, liyakat Jun 15 '15 at 3:42

  • This question does not appear to be about the Magento e-Commerce platform within the scope defined in the help center.
If this question can be reworded to fit the rules in the help center, please edit the question.

Solution 1

This moves out of stock products to the end of the list on page, not all over the pagination:

1.Add event observer:

<frontend>
    <events>
        <catalog_block_product_list_collection>
            <observers>
                <ssd_test>
                    <type>model</type>
                    <class>ssd_test/observer</class>
                    <method>catalogBlockProductCollectionBeforeToHtml</method>
                </ssd_test>
            </observers>
        </catalog_block_product_list_collection>
    </events>
</frontend>

2.Observer logic:

public function catalogBlockProductCollectionBeforeToHtml($observer)
{
    /**
     * @var $products Varien_Data_Collection
     */
    $products         = $observer->getEvent()->getCollection();
    $soldOuts         = array();
    if ($products instanceof Varien_Data_Collection) {
        foreach ($products as $product) {
            if (!$product->isSaleable()) {
                $products->removeItemByKey($product->getId());
                $soldOuts[] = $product;
            }
        }
        foreach ($soldOuts as $product) {
            $products->addItem($product);
        }
    }
    return $this;
}

3.Set "Display Out of Stock Products" to "Yes" on System->Configuration->Inventory.

Solution 2

This moves out of stock products to the end of the list within all over the pagination:

config.xml:

    <frontend>
        <events>
            <catalog_product_collection_load_before>
                <observers>
                    <review>
                        <type>model</type>
                        <class>ssd_test/observer</class>
                        <method>catalogProductCollectionLoadBefore</method>
                    </review>
                </observers>
            </catalog_product_collection_load_before>
        </events>
    </frontend>

Observer.php:

    public function catalogProductCollectionLoadBefore($observer)
    {
        $toolbar = Mage::getBlockSingleton('catalog/product_list_toolbar');
        if ($toolbar) {
            $products = $observer->getEvent()->getCollection();

            $stockId = Mage_CatalogInventory_Model_Stock::DEFAULT_STOCK_ID;
            $websiteId = Mage::app()->getStore($products->getStoreId())->getWebsiteId();

            $products->getSelect()->joinLeft(
                array('_inv' => $products->getResource()->getTable('cataloginventory/stock_status')),
                "_inv.product_id = e.entity_id and _inv.website_id=$websiteId and _inv.stock_id=$stockId",
                array('stock_status')
            );
            $products->addExpressionAttributeToSelect('in_stock', 'IFNULL(_inv.stock_status,0)', array());

            $products->getSelect()->reset('order');
            $products->getSelect()->order('in_stock DESC');

            if ($toolbar->getCurrentOrder()) {
                $products->addAttributeToSort($toolbar->getCurrentOrder(), $toolbar->getCurrentDirection());
            }
        }

        return $this;
    }

Set "Display Out of Stock Products" to "Yes" on System->Configuration->Inventory.

Above logics do not affect to your catalog sort/pagination functionality, only moves not salable products to the end.

  • Are you sure this will work? It seams it won't affect pagination, but it will move the out of stock products FROM THE CURRENT PAGE at the bottom. So if you go to the next page you might see in stock products after you saw on the previous page some out of stock ones. – Marius Aug 20 '14 at 14:20
  • Yes It will move out of stock products to the end of list on every page of pagination – mageUz Aug 20 '14 at 14:23
  • I think the task here was to move the out of stock products at the end of the list, not the page. So you should see the first N pages with in stock products and once you view an out of stock one, all others that come after that are out of stock. – Marius Aug 20 '14 at 14:28
  • Yes, I'll try to give another solution :) – mageUz Aug 20 '14 at 14:30
  • 1
    Solution 2 works like a charm! Thank you very much for this! – Derik Nel Dec 10 '15 at 13:18

I've implemented this functionality on my website.

  • Copy Collection.php from /app/code/core/Mage/Catalog/Model/Resource/Product/Collection.php to /app/code/local/Mage/Catalog/Model/Resource/Product/

  • Edit Collection.php, around line 1570 find text $storeId = $this->getStoreId();

  • Add the following lines directly bellow:

        $this->getSelect()->joinLeft(
        array('_inventory_table'=>$this->getTable('cataloginventory/stock_item')),
        "_inventory_table.product_id = e.entity_id",
        array('is_in_stock', 'manage_stock')
    );
    $this->addExpressionAttributeToSelect('on_top',
    '(CASE WHEN (((_inventory_table.use_config_manage_stock = 1) AND (_inventory_table.is_in_stock = 1)) OR  ((_inventory_table.use_config_manage_stock = 0) AND (1 - _inventory_table.manage_stock + _inventory_table.is_in_stock >= 1))) THEN 1 ELSE 0 END)',
     array());
    $this->getSelect()->order('on_top DESC');
    

Flush your cache and your products will now automatically sort the in stock products first and the out of stock products last.

  • 2
    Please refrain from recommending local core overrides. Would be much better to properly extend the Mage_Catalog_Model_Resource_Product_Collection class. – Reid Blomquist Aug 20 '14 at 16:26
  • Perhaps you can add your own answer and show us how to do that? – SR_Magento Aug 20 '14 at 17:40

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