1

I need to add an option in the Sort By dropdown which sorts the products with based on stock availability of the products.

So far i have created a plugin for setCollection methodMagento\Catalog\Block\Product\ProductList\Toolbar. Check the following code i am using to apply the sort order

public function afterSetCollection($subject)
    {
        $selectedDirection = strtolower($this->_toolbarModel->getDirection());

        if($this->_toolbarBlock->getCurrentOrder() == 'stock'){
            $collection = $subject->getCollection();
            $collection->addAttributeToSort('is_in_stock',$selectedDirection);        
            $collection->getSelect()->joinLeft(
                ['_inventory_table' => 'cataloginventory_stock_item'],
                "_inventory_table.product_id = e.entity_id",
                ['is_in_stock']
            );            
            $collection->getSelect()->order('is_in_stock',$selectedDirection);
            $collection->setOrder('is_in_stock',$selectedDirection);
            /*echo $collection->getSelect();die;*/
        }
        return $subject;
    }

When i print the sql query, it shows the Order By clause applied and if i execute it, it generates correct results, but the product list in the list page does not reflect the same order.

3 Answers 3

3

Path : Vendor\ModuleName\etc\di.xml

<?xml version="1.0"?>
    <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
        <type name="Magento\Catalog\Model\Layer">
            <plugin name="product_sort_by_stock" type="Company\ModuleName\Model\Plugin\Layer"/>
        </type>
    </config>

Path : Vendor\ModuleName\Model\Plugin\Layer.php

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Company\ModuleName\Model\Plugin;

/**
 * Catalog view layer model
 *
 * @api
 * @SuppressWarnings(PHPMD.LongVariable)
 * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
 * @since 100.0.2
 */
class Layer
{ 
    /**
     * Retrieve current layer product collection
     *
     * @return \Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    public function aroundgetProductCollection(\Magento\Catalog\Model\Layer $subject, \Closure $proceed)
    {
        $selectedDirection = 'DESC';
        $collection = $proceed(); 
        $collection->getSelect()->order('is_salable '. $selectedDirection);
        return $collection;
    }    
}

Read More

2
  • Something like this worked for me also. But I have a question how can we order items as per some other custom attribute.
    – Abid Malik
    Commented Aug 31, 2019 at 6:34
  • @Abid Malik ,You can follow below $collection->getSelect()->order('special_price', $selectedDirection); or $collection->getSelect()->order(new \Zend_Db_Expr("FIELD(e.custom_attribute, 1)"). $selectedDirection); #use Zend_Db_Expr Commented Sep 3, 2019 at 1:58
1

There is no need to use 'around' plugin as only the result should be 'modified'. I'd prefer 'after' plugin instead:

<?php

namespace Company\ModuleName\Plugin;

class Layer
{
    /**
     * @param \Magento\Catalog\Model\Layer $subject
     * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
     * @return \Magento\Catalog\Model\ResourceModel\Product\Collection
     */
    public function afterGetProductCollection(
        \Magento\Catalog\Model\Layer $subject,
        \Magento\Catalog\Model\ResourceModel\Product\Collection $collection
    ) {
        $collection->getSelect()->order('is_salable DESC');
        return $collection;
    }
}
0

Please update your code to sort according to current direction (By ASC or By DESC)

  $collection = $subject->getCollection();
  $collection->getSelect()->joinLeft(
         ['_inventory_table' => 'cataloginventory_stock_item'], 
         "_inventory_table.product_id = e.entity_id", ['qty']
  );
  $collection->getSelect()->order(['qty ' . $currentDirection]);

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.