>How to show Bestseller Products in Magento 2

How to show Bestseller Products in Magento 2

Since when our article “How to display bestseller products in Magento 1” was launched on Jan 16, 2018, we’ve gotten various qualified feedbacks and requested for the same title on Magento 2 as well.

Today we would love to guide you how to show bestseller products in Magento 2.

Create module

First of all, we need to create module to list bestseller products.

Create Block file with the path app/code/Bss/Bestsellerwidget/Block/Widget/Bestsellerdproduct.php:

<?php
namespace Bss\Bestsellerwidget\Block\Widget;
class Bestsellerdproduct extends \Magento\Framework\View\Element\Template implements \Magento\Widget\Block\BlockInterface
{
    protected $_template = 'widget/bestsellerdproduct.phtml';
        /**
    * Default value for products count that will be shown
    */
    const DEFAULT_PRODUCTS_COUNT = 10;
    const DEFAULT_IMAGE_WIDTH = 150;
    const DEFAULT_IMAGE_HEIGHT = 150;
    /**
    * Products count
    *
    * @var int
    */
    protected $productsCount;
    /**
    * @var \Magento\Framework\App\Http\Context
    */
    protected $httpContext;
    protected $resourceCollection;
    protected $productloader;
    protected $resourceFactory;
    /**
    * Catalog product visibility
    *
    * @var \Magento\Catalog\Model\Product\Visibility
    */
    protected $catalogProductVisibility;
    
    /**
    * Product collection factory
    *
    * @var \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory
    */
    protected $productCollectionFactory;
    
    /**
    * Image helper
    *
    * @var Magento\Catalog\Helper\Image
    */
    protected $imageHelper;
    /**
    * @var \Magento\Checkout\Helper\Cart
    */
    protected $cartHelper;
    /**
    * @param Context $context
    * @param \Magento\Catalog\Model\ResourceModel\Product\CollectionFactory $productCollectionFactory
    * @param \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility
    * @param \Magento\Framework\App\Http\Context $httpContext
    * @param array $data
    */

   public function __construct(
    \Magento\Catalog\Block\Product\Context $context,
        \Magento\Reports\Model\ResourceModel\Report\Collection\Factory $resourceFactory,
        \Magento\Reports\Model\Grouped\CollectionFactory $collectionFactory,
        \Magento\Reports\Helper\Data $reportsData,
        \Magento\Sales\Model\ResourceModel\Report\Bestsellers\CollectionFactory $resourceCollection,
        \Magento\Catalog\Model\ProductFactory $productloader,
        array $data = []
    ) {
        $this->resourceFactory = $resourceFactory;
        $this->_collectionFactory = $collectionFactory;
        $this->_reportsData = $reportsData;
        $this->imageHelper = $context->getImageHelper();
        $this->productloader = $productloader;
        $this->cartHelper = $context->getCartHelper();
        $this->resourceCollection = $resourceCollection;
        parent::__construct($context, $data);
    }
     /**
    * Image helper Object
    */
     public function imageHelperObj(){
        return $this->imageHelper;
    }
    /**
    * get featured product collection
    */
   public function getBestsellerProduct(){
    $limit = $this->getProductLimit();
     $resourceCollection = $this->resourceCollection->create();
     $resourceCollection->setPageSize($limit);
     return $resourceCollection;
   }
    /**
    * Get the configured limit of products
    * @return int
    */
    public function getProductLimit() {
     if($this->getData('productcount')==''){
         return DEFAULT_PRODUCTS_COUNT;
     }
        return $this->getData('productcount');
    }
    /**
    * Get the widht of product image
    * @return int
    */
    public function getProductimagewidth() {
     if($this->getData('imagewidth')==''){
         return DEFAULT_IMAGE_WIDTH;
     }
        return $this->getData('imagewidth');
    }
    /**
    * Get the height of product image
    * @return int
    */
    public function getProductimageheight() {
     if($this->getData('imageheight')==''){
         return DEFAULT_IMAGE_HEIGHT;
     }
        return $this->getData('imageheight');
    }
    /**
    * Get the add to cart url
    * @return string
    */
    public function getAddToCartUrl($product, $additional = [])
    {
         return $this->cartHelper->getAddUrl($product, $additional);
    }
    /**
    * Return HTML block with price
    *
    * @param \Magento\Catalog\Model\Product $product
    * @param string $priceType
    * @param string $renderZone
    * @param array $arguments
    * @return string
    * @SuppressWarnings(PHPMD.NPathComplexity)
    */
    public function getProductPriceHtml(
        \Magento\Catalog\Model\Product $product,
        $priceType = null,
        $renderZone = \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST,
        array $arguments = []
    ) {
        if (!isset($arguments['zone'])) {
            $arguments['zone'] = $renderZone;
        }
        $arguments['zone'] = isset($arguments['zone'])
            ? $arguments['zone']
            : $renderZone;
        $arguments['price_id'] = isset($arguments['price_id'])
            ? $arguments['price_id']
            : 'old-price-' . $product->getId() . '-' . $priceType;
        $arguments['include_container'] = isset($arguments['include_container'])
            ? $arguments['include_container']
            : true;
        $arguments['display_minimal_price'] = isset($arguments['display_minimal_price'])
            ? $arguments['display_minimal_price']
            : true;
            /** @var \Magento\Framework\Pricing\Render $priceRender */
        $priceRender = $this->getLayout()->getBlock('product.price.render.default');
        $price = '';
        if ($priceRender) {
            $price = $priceRender->render(
                \Magento\Catalog\Pricing\Price\FinalPrice::PRICE_CODE,
                $product,
                $arguments
            );
        }
        return $price;
    }
    public function loadProduct($id)
    {
        return $this->productloader->create()->load($id);
    }
}

Create file app/code/Bss/Bestsellerwidget/etc/module.xml to declare module.

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
    <module name="Bss_Bestsellerwidget" setup_version="1.0.0">
     <sequence>
                   <module name="Magento_Sales"/>
        </sequence>
      </module>
</config>

Create file app/code/Bss/Bestsellerwidget/etc/widget.xml to add widget using in CMS block/page.

<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Magento/Widget/etc/widget.xsd">
    <widget id="bss_bestsellerwidget" class="Bss\Bestsellerwidget\Block\Widget\Bestsellerdproduct">
        <label translate="true">Bestseller Product Widget</label>
        <description>Bss Bestseller Product Widget</description>
        <parameters>
            <parameter name="productcount" xsi:type="text"  visible="true" sort_order="1" >
                <label translate="true">Product Count</label>
            </parameter>
            <parameter name="imagewidth" xsi:type="text"  visible="true" sort_order="2" >
                <label translate="true">Image Width</label>
            </parameter>
            <parameter name="imageheight" xsi:type="text"  visible="true" sort_order="3" >
                <label translate="true">Image Height</label>
            </parameter>
        </parameters>
    </widget>
</widgets>

Create file app/code/Bss/Bestsellerwidget/view/frontend/templates/widget/bestsellerdproduct.phtml to display template at the frontend.

<?php
if ($exist = ($this->getBestsellerProduct() && $this->getBestsellerProduct()->getPageSize())) {
$fetProdCollection = $this->getBestsellerProduct();
$productcount = $this->getProductLimit();
$imagewidth = $this->getProductimagewidth();
$imageheight = $this->getProductimageheight();
 $mode = 'grid';
  $title = __('Bestseller Products');
 $type = 'widget-bestseller-grid';
 $image = 'bestseller_products_content_widget_grid';
}
?>
<?php if ($exist):?>
  <div class="block widget block-bestseller-products <?php /* @escapeNotVerified */ echo $mode; ?>">
        <div class="block-title">
            <strong role="heading" aria-level="2"><?php /* @escapeNotVerified */ echo $title; ?></strong>
        </div>
<div class="block-content">
 <?php /* @escapeNotVerified */ echo '<!-- ' . $image . '-->' ?>
 <div class="products-<?php /* @escapeNotVerified */ echo $mode; ?> <?php /* @escapeNotVerified */ echo $mode; ?>">
                <ol class="product-items <?php /* @escapeNotVerified */ echo $type; ?>">
                    <?php $iterator = 1; ?>
    <?php foreach ($fetProdCollection as $item):  
$prod = $block->loadProduct($item->getProductId());
    ?>
    <?php /* @escapeNotVerified */ echo($iterator++ == 1) ? '<li class="product-item">' : '</li><li class="product-item">' ?>
                        <div class="product-item-info">
                        <?php
            $imageUrl = $block->imageHelperObj()->init($prod, 'product_page_image_small')
                        ->setImageFile($prod->getFile())
                        ->resize($imagewidth,$imageheight)
                        ->getUrl();
?>
                            <a href="<?php /* @escapeNotVerified */ echo $prod->getProductUrl() ?>" class="product-item-photo">
                            <img src="<?php echo  $imageUrl;?>" alt="<?php echo $this->escapeHtml($prod->getName()) ?>" />
                            </a>
                            <div class="product-item-details">
                                <strong class="product-item-name">
                                    <a title="<?php echo $block->escapeHtml($prod->getName()) ?>"
                                    href="<?php /* @escapeNotVerified */ echo $prod->getProductUrl() ?>"
                                    class="product-item-link">
                                        <?php echo $block->escapeHtml($prod->getName()) ?>
                                    </a>
                                </strong>
                                <?php
                                echo $this->getProductPriceHtml($prod, $type);
                                ?>
                                    <div class="product-item-actions">
                                            <div class="actions-primary">
                                                <?php if ($prod->isSaleable()): ?>
                                                    <?php if ($prod->getTypeInstance()->hasRequiredOptions($prod)): ?>
                                                        <button class="action tocart primary"
                                                                data-mage-init='{"redirectUrl":{"url":"<?php /* @escapeNotVerified */ echo $block->getAddToCartUrl($prod) ?>"}}'
                                                                type="button" title="<?php /* @escapeNotVerified */ echo __('Add to Cart') ?>">
                                                            <span><?php /* @escapeNotVerified */ echo __('Add to Cart') ?></span>
                                                        </button>
                                                    <?php else: ?>
                                                        <?php
                                                            $postDataHelper = $this->helper('Magento\Framework\Data\Helper\PostHelper');
                                                            $postData = $postDataHelper->getPostData($block->getAddToCartUrl($prod), ['product' => $prod->getId()]);
                                                        ?>
                                                        <button class="action tocart primary"
                                                                data-post='<?php /* @escapeNotVerified */ echo $postData; ?>'
                                                                type="button" title="<?php /* @escapeNotVerified */ echo __('Add to Cart')>">
                                                            <span><?php /* @escapeNotVerified */ echo __('Add to Cart') ?></span>
                                                        </button>
                                                    <?php endif; ?>
                                                <?php else: ?>
                                                    <?php if ($prod->getIsSalable()): ?>
                                                        <div class="stock available"><span><?php /* @escapeNotVerified */ echo __('In stock') ?></span></div>
                                                    <?php else: ?>
                                                        <div class="stock unavailable"><span><?php /* @escapeNotVerified */ echo __('Out of stock') ?></span></div>
                                                    <?php endif; ?>
                                                <?php endif; ?>
                                            </div>
                                    </div>
                            </div>    
    </div>
                 <?php echo($iterator == count($fetProdCollection)+1) ? '</li>' : '' ?>
                    <?php endforeach ?>
</ol>
</div>
<?php endif;?>

Now we need to run command setup:upgrade and deploy (if need).

Frontend

After creating the module already, we need to display bestseller products on the frontend. We will create widget by going to “Content -> Widget -> Add Widget”.

In the field “Type”, please select “Bestseller Product Widget”.

We could place the bestseller product box in everywhere we want.

For example, if we would like to place at homepage, we could select “Content -> Pages -> select Homepage” then add code: {{widget type=”Bss\Bestsellerwidget\Block\Widget\Bestsellerdproduct” productcount=”10″ imagewidth=”170″ imageheight=”170″}}.

The result

We could see the bestseller product which we just created at the frontend.

Hopefully the article will help you!

< Previous Post
Next Post >