14

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

7

2 Answers 2

12

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.

11
  • 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
    Commented Aug 20, 2014 at 14:20
  • Yes It will move out of stock products to the end of list on every page of pagination
    – mageUz
    Commented Aug 20, 2014 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
    Commented Aug 20, 2014 at 14:28
  • Yes, I'll try to give another solution :)
    – mageUz
    Commented Aug 20, 2014 at 14:30
  • 1
    Solution 2 works like a charm! Thank you very much for this!
    – Derik Nel
    Commented Dec 10, 2015 at 13:18
0

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
  • 3
    Please refrain from recommending local core overrides. Would be much better to properly extend the Mage_Catalog_Model_Resource_Product_Collection class. Commented Aug 20, 2014 at 16:26
  • 1
    Perhaps you can add your own answer and show us how to do that?
    – SR_Magento
    Commented Aug 20, 2014 at 17:40

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