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!
How can we add category filter in this? I have to add this for particular category bestseller products.
In function getBestsellerProduct() of file
,
please add this code to filter by desired category.
$categories = [‘6′,’14’,’5′];
Hope this answer helps.
Regards.
The category filter is not working for me.
Please give us more information about your case so we can help you out more quickly.
Regards.
registration.php file is missing in your code and if anyone wants to use this extension then add registration.php file in the root of extension.
Here is the code which you need to add.
<?php
/* file: app/code/Bss/Bestsellerwidget/registration.php */
\Magento\Framework\Component\ComponentRegistrar::register(
\Magento\Framework\Component\ComponentRegistrar::MODULE,
'Bss_Bestsellerwidget',
__DIR__
);
Thanks so much for your contribution.
The registration.php file is required whenever you create a module. In this article, we focus on giving the solution to showing bestseller products, hence, there might be missing some basic steps.
For those wanting to learn how to create a module from the start, you can refer to here.
Is this code working correctly if products order are with configurable?
Unfortunately no.
Hereby we suggest you a basic way to get bestseller products from Magento database. If you want to apply it to configurable products, it might be far more complicated. That time, you should use Magento 2 extensions to ensure all functions work well.
Regard.
I tried your code but iam not getting the products displayed in frontend only title bestseller products.