Magento – How to add custom sort by option filter in tool bar in magento2

attributescustom-optionsmagento2sortingtoolbar

I want to custom sort by option filter attribute add in tool bar section. Currently Magento 2 provide Position , Product Name , Price And Sorting option to low to high. But i need to change all sorting option Like Price High to Low , Price Low to High.

Best Answer

I created these custom sort by options:

  • price high - low --> (including all forms of discounts)
  • price low - high --> (including all forms of discounts)
  • name a-z
  • name z-a
  • newest
  • oldest

by creating a plugin to bypass the default functionality of the product sorter which can be found here:

Magento\Catalog\Block\Product\ProductList\Toolbar

and

Magento\Catalog\Model\Config

You start by creating your own module and registering it.

Then create:

{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\Config">
        <plugin name="Vendor_ModuleName::addCustomSortOptions" type="Vendor\ModuleName\Plugin\Model\Config" />
    </type>
    <type name="Magento\Catalog\Block\Product\ProductList\Toolbar">
        <plugin name="Vendor_ModuleName::implementCustomSortOptions" type="Vendor\ModuleName\Plugin\Product\ProductList\Toolbar" />
    </type>
</config>

Create

{Vendor}/{ModuleName}/Plugin/Model/Config.php

<?php
namespace Vendor\ModuleName\Plugin\Model;

class Config
{
    /**
     * Adding custom options and changing labels
     *
     * @param \Magento\Catalog\Model\Config $catalogConfig
     * @param [] $options
     * @return []
     */
    public function afterGetAttributeUsedForSortByArray(\Magento\Catalog\Model\Config $catalogConfig, $options)
    {
        //Remove default sorting options
        unset($options['position']);
        unset($options['name']);
        unset($options['price']);

        //Change label of default sorting options if needed
        //$options['position'] = __('Relevance');

        //New sorting options
        $options['price_desc'] = __('Price High - Low');
        $options['price_asc'] = __('Price Low - High');
        $options['newest'] = __('Newest');
        $options['oldest'] = __('Oldest');
        $options['name_az'] = __('Product Name A - Z');
        $options['name_za'] = __('Product Name Z - A');

        return $options;
    }
}

Create

{vendor}/{modulename}/Plugin/Product/ProductList/Toolbar.php

<?php
namespace Vendor\ModuleName\Plugin\Product\ProductList;

class Toolbar
{
    /**
    * Plugin
    *
    * @param \Magento\Catalog\Block\Product\ProductList\Toolbar $subject
    * @param \Closure $proceed
    * @param \Magento\Framework\Data\Collection $collection
    * @return \Magento\Catalog\Block\Product\ProductList\Toolbar
    */
    public function aroundSetCollection(
        \Magento\Catalog\Block\Product\ProductList\Toolbar $toolbar,
        \Closure $proceed,
        $collection
    ) {
        $this->_collection = $collection;
        $currentOrder = $toolbar->getCurrentOrder();
        $currentDirection = $toolbar->getCurrentDirection();
        $result = $proceed($collection);

        if ($currentOrder) {
            switch ($currentOrder) {

            case 'newest':
                $this->_collection
                    ->getSelect()
                    ->order('e.created_at DESC');
            break;

            case 'oldest':
                $this->_collection
                    ->getSelect()
                    ->order('e.created_at ASC');

            break;

            case 'price_desc':
                $this->_collection
                    ->getSelect()
                    ->order('price_index.min_price DESC');
            break;

            case 'price_asc':
                $this->_collection
                    ->getSelect()
                    ->order('price_index.min_price ASC');
            break;

            case 'name_az':
                $this->_collection
                    ->getSelect()
                    ->order('e.name ASC');
            break;

            case 'name_za':
                $this->_collection
                    ->getSelect()
                    ->order('e.name DESC');
            break;

            default:        
                $this->_collection
                    ->setOrder($currentOrder, $currentDirection);
            break;

            }
        }
        //var_dump((string) $this->_collection->getSelect()); You can use this to get a list of all the available sort fields
        return $result;
    }
}
Related Topic