5

I want to display price range for configurable products instead of the minimal price in category listing. enter image description here

1 Answer 1

16

You need to pluginize getProductPrice method.

SR/Stackexchange/etc/frontend/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\Block\Product\ListProduct">
        <plugin name="SR_Stackexchange:price_range" type="SR\Stackexchange\Plugin\Block\Product\ListProduct" sortOrder="1"/>
    </type>
</config>

SR/Stackexchange/Plugin/Block/Product/ListProduct.php


namespace SR\Stackexchange\Plugin\Block\Product;

use Magento\ConfigurableProduct\Model\Product\Type\Configurable;

class ListProduct
{
    /**
     * @var \Magento\Catalog\Block\Product\ListProduct
     */
    protected $listProductBlock;

    /**
     * @var Configurable
     */
    protected $configurableProduct;

    /**
     * @var \Magento\Framework\Pricing\Helper\Data
     */
    protected $pricingHelper;

    /**
     * @var \Psr\Log\LoggerInterface
     */
    protected $logger;

    /**
     * ListProduct constructor.
     *
     * @param Configurable $configurableProduct
     * @param \Magento\Framework\Pricing\Helper\Data $pricingHelper
     */
    public function __construct(
        Configurable $configurableProduct,
        \Magento\Framework\Pricing\Helper\Data $pricingHelper,
        \Psr\Log\LoggerInterface $logger
    ) {
        $this->configurableProduct = $configurableProduct;
        $this->pricingHelper = $pricingHelper;
        $this->logger = $logger;
    }

    /**
     * @param \Magento\Catalog\Block\Product\ListProduct $subject
     * @param \Closure $proceed
     * @param \Magento\Catalog\Model\Product $product
     * @return string
     */
    public function aroundGetProductPrice(
        \Magento\Catalog\Block\Product\ListProduct $subject,
        \Closure $proceed,
        \Magento\Catalog\Model\Product $product
    ) {

        if (Configurable::TYPE_CODE !== $product->getTypeId()) {
            return $proceed($product);
        }

        $this->listProductBlock = $subject;
        $priceText = $this->getPriceRange($product);

        return $priceText;
    }

    /**
     * Get configurable product price range
     *
     * @param $product
     * @return string
     */
    public function getPriceRange($product)
    {
        $childProductPrice = [];
        $childProducts = $this->configurableProduct->getUsedProducts($product);
        foreach($childProducts as $child) {
            $price = number_format($child->getPrice(), 2, '.', '');
            $finalPrice = number_format($child->getFinalPrice(), 2, '.', '');
            if($price == $finalPrice) {
                $childProductPrice[] = $price;
            } else if($finalPrice < $price) {
                $childProductPrice[] = $finalPrice;
            }
        }

        $max = $this->pricingHelper->currencyByStore(max($childProductPrice));
        $min = $this->pricingHelper->currencyByStore(min($childProductPrice));
        if($min==$max){
            return $this->getPriceRender($product, "$min", '');
        } else {
            return $this->getPriceRender($product, "$min-$max", '');
        }
    }

    /**
     * Price renderer
     *
     * @param $product
     * @param $price
     * @return mixed
     */
    protected function getPriceRender($product, $price, $text='')
    {
        return $this->listProductBlock->getLayout()->createBlock('Magento\Framework\View\Element\Template')
            ->setTemplate('SR_Stackexchange::product/price/range/price.phtml')
            ->setData('price_id', 'product-price-'.$product->getId())
            ->setData('display_label', $text)
            ->setData('product_id', $product->getId())
            ->setData('display_value', $price)->toHtml();
    }
}

SR/Stackexchange/view/frontend/templates/product/price/range/price.phtml


<?php /** @var \Magento\Framework\Pricing\Render\Amount $block */ ?>

<div class="price-box range second price-final_price" data-role="priceBox" data-product-id="<?php /* @escapeNotVerified */ echo $block->getProductId() ?>">
    <span class="special-price">
        <span class="price-container price-final_price">
            <?php if ($block->getDisplayLabel()): ?>
                <span class="price-label"><?php /* @escapeNotVerified */ echo $block->getDisplayLabel(); ?></span>
            <?php endif; ?>
            <span <?php if ($block->getPriceId()): ?> id="<?php /* @escapeNotVerified */ echo $block->getPriceId() ?>"<?php endif;?>
                data-price-amount=""
                data-price-type="finalPrice1"
                class="price-wrapper">
                <span class="price"><?php /* @escapeNotVerified */ echo $block->getDisplayValue();?></span>
            </span>
        </span>
    </span>
</div>

Clear Cache.

14
  • Shows some error in this area else if($finalPrice pricingHelper->currencyByStore(max($childProductPrice)); $min = $this->pricingHelper->currencyByStore(min($childProductPrice)); Oct 13, 2017 at 6:50
  • Also some error in the phtml file. Oct 13, 2017 at 6:57
  • Show your error. It's tested code and working fine.
    – Sohel Rana
    Oct 13, 2017 at 7:00
  • Check updated code for SR/Stackexchange/view/frontend/templates/product/price/range/price.phtml
    – Sohel Rana
    Oct 13, 2017 at 7:02
  • 1
    SR/Stackexchange = VendorName/ModuleName, Location should be app/code/ @MarioM.
    – Sohel Rana
    Dec 16, 2017 at 14:59

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.