4

I am working on a Magento 2.1.7 shop. To achieve this, I have created a child-theme of Magento Blank.

On the home page, I want to insert a "Bestsellers" widget via the Magento admin, like the one below:

enter image description here

By default, Magento only offers the possibility to insert a "New products" widget.

What is the best approach to insert a "Bestsellers" widget too?

UPDATE: I have installed the module, run the tasks:

php bin/magento module:enable Anshu_Bestsellerwidget
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy
php bin/magento deploy:mode:set developer

The module does not show in the frontend and the background it looks like this:

enter image description here

What is wrong?

Thank you!

1 Answer 1

4

I have created something similar using following code.

app/code/Anshu/Bestsellerwidget/registration.php

<?php

\Magento\Framework\Component\ComponentRegistrar::register(
    \Magento\Framework\Component\ComponentRegistrar::MODULE,
    'Anshu_Bestsellerwidget',
    __DIR__
);

app/code/Anshu/Bestsellerwidget/etc/module.xml

<?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="Anshu_Bestsellerwidget" setup_version="1.0.0">
    </module>
</config>

app/code/Anshu/Bestsellerwidget/etc/widget.xml

<?xml version="1.0" encoding="UTF-8"?>
<widgets xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Widget:etc/widget.xsd">
    <widget id="anshu_bestsellerwidget" class="Anshu\Bestsellerwidget\Block\Product\Widget\BestsellerWidget" ttl="86400">
        <label translate="true">Bestseller Products List</label>
        <description translate="true">List of Best Selling Products</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>
            <parameter name="cache_lifetime" xsi:type="text" visible="true">
                <label translate="true">Cache Lifetime (Seconds)</label>
                <description translate="true">86400 by default, if not set. To refresh instantly, clear the Blocks HTML Output cache.</description>
            </parameter>
        </parameters>
    </widget>
</widgets>

app/code/Anshu/Bestsellerwidget/Block/Product/Widget/BestsellerWidget.php

<?php

namespace Anshu\Bestsellerwidget\Block\Product\Widget;

/**
 * Best Seller products widget
 */
class BestsellerWidget extends \Magento\Framework\View\Element\Template implements \Magento\Widget\Block\BlockInterface
{
    protected $_template = 'bestsellerproduct.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 $_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,
        array $data = []
    ) {
        $this->_resourceFactory = $resourceFactory;
        $this->_collectionFactory = $collectionFactory;
        $this->_reportsData = $reportsData;
        $this->_imageHelper = $context->getImageHelper();
        $this->_cartHelper = $context->getCartHelper();
        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->_resourceFactory->create('Magento\Sales\Model\ResourceModel\Report\Bestsellers\Collection');
        $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;
    }
}

app/code/Anshu/Bestsellerwidget/view/frontend/templates/bestsellerproduct.phtml

<?php
if ($exist = ($this->getBestsellerProduct() && $this->getBestsellerProduct()->getPageSize())) {
    $fet_prodcollection = $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 ($fet_prodcollection as $item):

                    $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
                    $_product = $objectManager->get('Magento\Catalog\Model\Product')->load($item->getProductId());
                    ?>

                    <?php /* @escapeNotVerified */ echo($iterator++ == 1) ? '<li class="product-item">' : '</li><li class="product-item">' ?>
                    <div class="product-item-info">
                        <?php

                        $image_url = $block->imageHelperObj()->init($_product, 'product_page_image_small')
                            ->setImageFile($_product->getFile())
                            ->resize($imagewidth,$imageheight)
                            ->getUrl();

                        ?>
                        <a href="<?php /* @escapeNotVerified */ echo $_product->getProductUrl() ?>" class="product-item-photo">
                            <img src="<?php echo  $image_url;?>" alt="<?php echo $this->escapeHtml($_product->getName()) ?>" />
                        </a>
                        <div class="product-item-details">
                            <strong class="product-item-name">
                                <a title="<?php echo $block->escapeHtml($_product->getName()) ?>"
                                   href="<?php /* @escapeNotVerified */ echo $_product->getProductUrl() ?>"
                                   class="product-item-link">
                                    <?php echo $block->escapeHtml($_product->getName()) ?>
                                </a>
                            </strong>
                            <?php
                            echo $this->getProductPriceHtml($_product, $type);
                            ?>

                            <div class="product-item-actions">

                                <div class="actions-primary">
                                    <?php if ($_product->isSaleable()): ?>
                                        <?php if ($_product->getTypeInstance()->hasRequiredOptions($_product)): ?>
                                            <button class="action tocart primary"
                                                    data-mage-init='{"redirectUrl":{"url":"<?php /* @escapeNotVerified */ echo $block->getAddToCartUrl($_product) ?>"}}'
                                                    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($_product), ['product' => $_product->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 ($_product->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($fet_prodcollection)+1) ? '</li>' : '' ?>
                <?php endforeach ?>
            </ol>
        </div>
<?php } ?>

I have taken reference from https://github.com/emizentech/magento2-best-seller
I hope this will be helpful.

22
  • Is that an entire module you made? Commented Nov 15, 2017 at 10:09
  • How would you adapt this solution to Magento 2.1.7? Commented Nov 15, 2017 at 10:32
  • You can customize above code/module according to your requirement Commented Nov 15, 2017 at 10:42
  • The article you have shared is for Magento1 and will not work in Magento2 Commented Nov 15, 2017 at 10:43
  • 1
    should use return self::DEFAULT_IMAGE_HEIGHT; instead of return DEFAULT_IMAGE_HEIGHT; Good work it save my time
    – HaFiz Umer
    Commented Sep 24, 2019 at 7:23

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.