Greetings! I'm Aneesh Sreedharan, CEO of 2Hats Logic Solutions. At 2Hats Logic Solutions, we are dedicated to providing technical expertise and resolving your concerns in the world of technology. Our blog page serves as a resource where we share insights and experiences, offering valuable perspectives on your queries.
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!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | <?php // File: app/code/YourVendor/YourModule/Block/Product/ShippingRates.php namespace YourVendorYourModuleBlockProduct; use MagentoFrameworkViewElementTemplate; use MagentoCatalogApiProductRepositoryInterface; use MagentoFrameworkViewElementTemplateContext; use MagentoFrameworkRegistry; 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, MagentoQuoteModelQuoteFactory $quoteFactory, MagentoQuoteModelQuoteAddressRateCollectorInterface $shippingRateCollector, MagentoQuoteModelQuoteAddressRateRequestFactory $rateRequestFactory, MagentoFrameworkPricingPriceCurrencyInterface $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 = MagentoFrameworkAppObjectManager::getInstance(); // Create a new quote $quote = $this->quoteFactory->create(); $quote->getShippingAddress()->setCountryId('US'); $quote->addProduct($product); // Create a RateRequest object $item = $objectManager->create('MagentoQuoteModelQuoteItem')->setProduct($product)->setQty(1); $item->setQuote($quote); $store = $objectManager->create('MagentoStoreModelStore')->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 –>
1 2 3 4 5 6 7 8 9 10 11 | <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 –>
1 2 3 4 5 6 7 | <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="YourVendorYourModuleBlockProductShippingRates" 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.