By In Magento

Show ‘out of stock’ products as last

Customer behavior studies shows that customers check products on first page, if searched product is not there they will only small number will go to second page or third page. Most likely they will try to use search or redefine there search parameters to get better results. That is why is important to display on first page products that are ‘in stock’ and can be purchased right away.

Magento offer several options how to sort products on catalog page, with this little snippet we will extend that feature by keeping same order but ‘out of stock’ products will be displayed as last on catalog page.

There are many ways to do that however we will go for simplest one, by copying Magento files into our ‘local’ folder, or course same code can be wrapped up in form of module for more effective use. For example we want to use this feature only on ‘Sale’ category to effectively keep available products on top of list.

First step would be to copy file ‘Toolbar.php’ from Magento core folder to our local folder:
/app/code/local/Mage/Catalog/Block/Product/List/Toolbar.php

than open file in editor and find function ‘setCollection’ and copy complete code. We will rename new function from ‘setCollection’ to ‘setCatalogCollection’ and add code that will sort products by stock status. New function should look like this:

public function setCatalogCollection($collection)
{
$this->_collection = $collection;

$this->_collection->setCurPage($this->getCurrentPage());

// we need to set pagination only if passed value integer and more that 0
$limit = (int)$this->getLimit();
if ($limit) {
$this->_collection->setPageSize($limit);
}

if ($this->getCurrentOrder()) {
$this->_collection->joinField('inventory_in_stock', 'cataloginventory_stock_item', 'is_in_stock', 'product_id=entity_id','is_in_stock>=0', 'left')->setOrder('inventory_in_stock', 'desc');
$this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
}
return $this;
}

We will need to copy one more from Magento core folder to our local folder:
/app/code/local/Mage/Catalog/Block/Product/List.php

In ‘List.php’ file find line:
$toolbar->setCollection($collection);
and replace it with our new function:
$toolbar->setCatalogCollection($collection);

Save all changes, refresh cache and check front end to see how code works. If everything is done properly your catalog page ordering will be adjusted and ‘out of stock’ products will be listed as last in collection.

It is important not to overwrite Magento default function ‘setCollection’ since it might happen that some 3rd party modules will use it and can cause site to crash (issue confirmed with free blog extensions).

I hope that this little trick with help you, if I have some free time in next few weeks I will try to create module to save you time and spare you from editing files.

32 Responses to Show ‘out of stock’ products as last

  1. Andrius says:

    Works on CE 1.9.2.3 – thanks!

  2. Vitazzz says:

    Is there a way to make it work with configurable products? So that when all options are out of stock, then the parent configurable will go down in the list.

    • Hello,
      thanks for comment, will it should work with configurable products as well. As far as I know when all options are ‘out of stock’ main product should be set out of stock too automatically, I can test this particular case to be sure that it works.

      Cheers !

  3. Bernardo says:

    It works fine,

    Thank you.

  4. Jon-Michael B. says:

    I am having real trouble with this, and any answer involving adding files to my local directory. I am on 1.9.2.1 and cannot get this solution to work. If you have any suggestions, tips, or tricks that may apply to my version please let me know. Thank you.

  5. Daniel says:

    Hi,

    This worked for me fine on category pages, but it broke search result pages.
    http://pastebin.com/nubpD3UT
    Any ideas?

  6. Akash Rajput says:

    Hello,

    Hope you’re doing great. I want to order my recently added products first but also place the out of stock products in last, Is it possible?

    The main reason is out of stock products render the page uneven.

    Current Code using..

    if(($this->getCurrentOrder())==’position’){
    $this->_collection->setOrder(‘entity_id’,’desc’);

  7. Toshi says:

    Hi,

    Unfortunately it will not work for me on CE 1.9.2.2
    Ik don’t get warnings or something, it just doesn’t work. Do you know what the problem is?

    Kind regards,

    Toshi

  8. vipin says:

    This is not working for me for configurable products, Magento 1.9
    can you give any solution for that ?

  9. Siva says:

    Thank you. It worked perfectly and helped me a lot lot.

  10. JUSTIN D says:

    Works Great! 1.9.3.6

  11. Will this also work when products are searched? So if someone searches for Jack it will show the OOS products last.? We use Sphinx search extension

  12. Sreedarsh says:

    Hi , i am getting an error like this after following your steps

    ‘Joined field with this alias is already declared’.Please help.

    • Hello,
      please check code that create product collection and look for ‘joinField’ function, because alias must be unique.
      You can also try to dump MySql query and there you should be able to see all joined fields and possible duplicate entry.

      Thanks !

      • Sreedarsh says:

        SELECT `e`.*, `price_index`.`price`, `price_index`.`tax_class_id`, `price_index`.`final_price`, IF(price_index.tier_price IS NOT NULL, LEAST(price_index.min_price, price_index.tier_price), price_index.min_price) AS `minimal_price`, `price_index`.`min_price`, `price_index`.`max_price`, `price_index`.`tier_price`, `at_inventory_in_stock`.`is_in_stock` AS `inventory_in_stock` FROM `catalog_product_entity` AS `e` INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND cat_index.category_id IN(’37’) INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = ‘1’ AND price_index.customer_group_id = 0 LEFT JOIN `cataloginventory_stock_item` AS `at_inventory_in_stock` ON (at_inventory_in_stock.`product_id`=e.entity_id) AND (is_in_stock>=0)

        The is the mysql query output.Can u please find the problem

  13. Bharat says:

    its not worked in 1933 version can you please another way for sort out that?

    • Hello,
      it should work, there are no mayor changes in 1933 compering previous versions.
      Did you tested code on clean Magento installation or there are some other 3rd party modules installed ?

      Thanks,
      Milan

  14. Chris says:

    Hi, your function doesn’t work well. Sometimes articles are displayed Twice or not displayed at all -> you can have article 1 on page1 and article 1 on page3 (specially if category order is set to 0). If you list all pages you may not see all products even if the total count is correct. I was crazy by not finding some products sometimes in the category then discovered the bug and reverted back to $toolbar->setCollection($collection); Hope you can reproduce it. I have around 150 articles with 34 / page. Basically products without category positions are displayed ramdomly in the segment.

    • Hello Chris,
      I didn’t notice such issue so far and used same code quite often.
      I am familiar with issue and found that it was caused by some of popular ‘multi select’ modules, that allow you to multi select attributes in ‘Shop by’ section.

      At this moment I don’t work much with Magento 1.x so I can’t tell you when I will have chance to test reported bug.

      Cheers !

Leave a Reply

Your email address will not be published. Required fields are marked *