I have a main category "Computer" with 3 sub categories:

  • Laptop
  • Storage
  • Software

I know how can I get a sub category. But I need best the selling product for each category, for example:


  • Product Laptop1
  • Product Laptop2 (This 2 product is best seller product for laptop category)


  • Product Storage1
  • Product Storage2 (This 2 product is best seller product for storage category)


  • Product Software1
  • Product Software2 (This 2 product is best seller product for software category)

My code to get the category list for the main category is:

public function __construct(
        Template\Context $context, 
        \Magento\Catalog\Model\Layer\Resolver $layerResolver, 
        \Magento\Framework\Registry $registry, 
        \Magento\Catalog\Helper\Category $categoryHelper, 
        \Magento\Catalog\Model\CategoryFactory  $categoryFactory,
        array $data = array()) 
        parent::__construct($context, $layerResolver, $registry, $categoryHelper,$data);
        $this->_categoryFactory = $categoryFactory;
        $this->_collectionFactory = $collectionFactory;

    public function getCategoryList()
      $_category  = $this->getCurrentCategory();
      $collection = $this->_categoryFactory->create()->getCollection()->addAttributeToSelect('*')
              ->addAttributeToFilter('is_active', 1)
              ->setOrder('position', 'ASC')
      return $collection;


1 Answer 1


Check my code below for more information :

You can also download my extension from Github. https://github.com/hirenrk4/Magento-2-Best-Seller

This way user can get a Category and sub category best the selling product for each category I've created the module following your instructions to Best sellerFilter On category list Page Filter.


    namespace Hiren\BestsellerFilter\Block\Product\ProductList;

    class Toolbar extends \Magento\Catalog\Block\Product\ProductList\Toolbar
        public function setCollection($collection)
                    'e.entity_id = sales_order_item.product_id', 
                    ->order('qty_ordered '.$this->getCurrentDirectionReverse());

            $this->_collection = $collection;


            $limit = (int)$this->getLimit();
            if ($limit) {
            if ($this->getCurrentOrder()) {
                $this->_collection->setOrder($this->getCurrentOrder(), $this->getCurrentDirection());
            return $this;

        public function getCurrentDirectionReverse() {
                if ($this->getCurrentDirection() == 'asc') {
                    return 'desc';
                } elseif ($this->getCurrentDirection() == 'desc') {
                    return 'asc';
                } else {
                    return $this->getCurrentDirection();


app/code/Hiren/BestsellerFilter/registration.php :




    "name": "Hiren/bestsellerfilter",
    "description": "Magento 2 custom module to add custom best seller filter to product list toolbar",
    "require": {
        "magento/framework": "~100.0"
    "type": "magento2-module",
    "version": "3.0.3",
    "license": [
    "autoload": {
        "files": [ "registration.php" ],
        "psr-4": {
            "Hiren\\BestsellerFilter\\": ""
    "extra": {
        "map": [


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../Store/etc/config.xsd">


<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../lib/internal/Magento/Framework/Module/etc/module.xsd">
    <module name="Hiren_BestsellerFilter" setup_version="1.0.0" schema_version="1.0.0">


<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    <preference for="Magento\Catalog\Block\Product\ProductList\Toolbar" type="Hiren\BestsellerFilter\Block\Product\ProductList\Toolbar"/>
    <preference for="Magento\Catalog\Model\Config" type="Hiren\BestsellerFilter\Model\Config"/>


namespace Hiren\BestsellerFilter\Model;

class Config extends \Magento\Catalog\Model\Config
    public function getAttributeUsedForSortByArray()
       $options = ['bestseller' => __('Best Seller')];
        foreach ($this->getAttributesUsedForSortBy() as $attribute) {
            /* @var $attribute \Magento\Eav\Model\Entity\Attribute\AbstractAttribute */
            $options[$attribute->getAttributeCode()] = $attribute->getStoreLabel();

       return $options;
  • Hi Hiren, good work, can you add a bit of explanation how Toolbar.php and Config.php work, 'showing your working' if you will, I look at Toolbar.php and it might just be me but I don't understand how or why it works and why "$this->getCurrentOrder()" doesnt fail because $this, in my unpacking of the code would hold a null value
    – John
    May 25, 2018 at 7:36
  • @hlren Can you tell how to get top 3 most purchased categories? How to implement that? I need the categories list instead of products list. Jan 8, 2020 at 14:39

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.