Estimating Shipping Rate on Product Details Page in Magento

e-commerceMagentoPHP
Estimating Shipping Rate on Product Details Page in Magento

To display the shipping rates on the product view page in Magento 2, you can use a custom block and template. Just follow these simple steps to make it happen:

Create a Custom Module:

If you don’t have a custom module yet, it’s a great idea to create one following the best practices for module creation in Magento 2.

Create a Block Class:

In your custom module, let’s create a block class to handle the super cool logic for obtaining shipping rates!

<?php
// File: app/code/YourVendor/YourModule/Block/Product/ShippingRates.php



namespace YourVendor\YourModule\Block\Product;
use Magento\Framework\View\Element\Template;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\Framework\View\Element\Template\Context;
use Magento\Framework\Registry;
class ShippingRates extends Template
{
protected $productRepository;
protected $quoteFactory;
protected $shippingRateCollector;
protected $rateFactory;
protected $rateRequestFactory;
protected $registry;
protected $priceCurrency;
protected $_template = 'YourVendor_YourModule::product/shipping_rates.phtml';
public function __construct(
        Context $context,
        \Magento\Quote\Model\QuoteFactory $quoteFactory,
        \Magento\Quote\Model\Quote\Address\RateCollectorInterface $shippingRateCollector,
        \Magento\Quote\Model\Quote\Address\RateRequestFactory $rateRequestFactory,
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
        ProductRepositoryInterface $productRepository,
        Registry $registry,
        array $data = []
    ) {
        parent::__construct($context, $data);
        $this->quoteFactory = $quoteFactory;
        $this->shippingRateCollector = $shippingRateCollector;
        $this->rateRequestFactory = $rateRequestFactory;
        $this->productRepository = $productRepository;
        $this->registry = $registry;
        $this->priceCurrency = $priceCurrency;
        //Initialize the storemanager
        $this->storeManager = $context->getStoreManager();
        // other constructor logic
    }
    /**
     * Retrieves the product ID.
     *
     * @return mixed The product ID.
     */
    public function getProductId()
    {
        $currentProduct = $this->registry->registry('current_product');
        if ($currentProduct) {
            return $currentProduct->getId();
        }
        return null;
    }
    public function getShippingRates($productId)
    {
        
        $product = $this->productRepository->getById($productId);
        $storeId = $this->storeManager->getStore()->getId();
        $zipcode = "90210";
        $country = 'US'; //United States
        $objectManager = \Magento\Framework\App\ObjectManager::getInstance();
        // Create a new quote
        $quote = $this->quoteFactory->create();
        $quote->getShippingAddress()->setCountryId('US');
        $quote->addProduct($product);
       
        // Create a RateRequest object
        $item = $objectManager->create('Magento\Quote\Model\Quote\Item')->setProduct($product)->setQty(1);
        $item->setQuote($quote);
        $store = $objectManager->create('Magento\Store\Model\Store')->load($storeId);
        $rateRequest = $this->rateRequestFactory->create()->setAllItems(array($item));
        $rateRequest->setStoreId($storeId);
        $rateRequest->setDestCountryId($country)
        ->setPackageValue($product->getFinalPrice())
        ->setOrigPostcode($zipcode)  
        ->setPackageValueWithDiscount($product->getFinalPrice())
        ->setPackageWeight($product->getWeight())
        ->setPackageQty(1)
        ->setPackagePhysicalValue($product->getFinalPrice())
        ->setFreeMethodWeight(0)
        ->setStoreId($store->getId())
        ->setWebsiteId($store->getWebsiteId())
        ->setFreeShipping(0)
        ->setBaseCurrency($store->getBaseCurrency())
        ->setBaseSubtotalInclTax($product->getFinalPrice());
       $rates = $this->shippingRateCollector->collectRates($rateRequest)->getResult();
          
        $data = [];
        foreach ($rates->getAllRates() as $rate) {
            if ($rate instanceof Mage_Shipping_Model_Rate_Result_Error) {
                $errors[$rate->getCarrierTitle()] = 1;
            } else {
                $k = $rate->getCarrierTitle();
                $price = $this->priceCurrency->format($rate->getPrice(), true, 2, null, null);
                $data[$k] = $price;
            }
        }
        return $data;
    }
}

You can change the zip code and country in the code above to match the customer’s details. So, if you want to put in their zip code and country from the session, you can do that too!

Create a Template File:

You gotta make a template file if you wanna show the shipping rates

<!– File: app/code/YourVendor/YourModule/view/frontend/templates/product/shipping_rates.phtml –>

<div class="shipping-rates">
<?php
$productId = $block->getProductId(); // Assuming you set the product ID in your block
$rates = $block->getShippingRates($productId);

foreach ($rates as $method => $rate) {
    echo $method . " : ". $rate; // Customize this part based on your needs
    echo "<br>";
}
?>
</div>

Create a Layout XML File:

Create a layout XML file in your module to tell the system where you want the block to show up.

<!– File: app/code/YourVendor/YourModule/view/frontend/layout/catalog_product_view.xml –>

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
    <body>
        <referenceContainer name="product.info.main">
            <block class="YourVendor\YourModule\Block\Product\ShippingRates" name="product.shipping.rates" template="YourVendor_YourModule::product/shipping_rates.phtml" />
        </referenceContainer>
    </body>
</page>

Bingo!!! You’re all done. Just run the “di:compile” and “cache:clear” commands now.

So, I tried this out in Magento 2.4, but I think it should work the same for other versions too. Just keep in mind that the dependency injections might be a bit different depending on the Magento version.

Comments are closed.

2hats Logic HelpBot