Overide form.phtml
in vendor/magento/module_catalog/templates/product/view/form.phtml
, and change form action to custom controller.
app/design/frontend/Vendor/Module/Magento_Catalog/templates/product/view/form.phtml
<?php $_helper = $this->helper('Magento\Catalog\Helper\Output'); ?>
<?php $_product = $block->getProduct();
$formSubmitUrl = $this->getUrl('routeId/path/controller');
?>
<div class="product-add-form">
<form data-product-sku="<?= $block->escapeHtml($_product->getSku()) ?>"
action="<?= /* @NoEscape */ $formSubmitUrl ?>" method="post"
id="product_addtocart_form"<?php if ($_product->getOptions()): ?> enctype="multipart/form-data"<?php endif; ?>>
<input type="hidden" name="product" value="<?= /* @escapeNotVerified */ $_product->getId() ?>" />
<input type="hidden" name="selected_configurable_option" value="" />
<input type="hidden" name="related_product" id="related-products-field" value="" />
<?= $block->getBlockHtml('formkey') ?>
<?= $block->getChildHtml('form_top') ?>
<?php if (!$block->hasOptions()):?>
<?= $block->getChildHtml('product_info_form_content') ?>
<?php else:?>
<?php if ($_product->isSaleable() && $block->getOptionsContainer() == 'container1'):?>
<?= $block->getChildChildHtml('options_container') ?>
<?php endif;?>
<?php endif; ?>
<?php if ($_product->isSaleable() && $block->hasOptions() && $block->getOptionsContainer() == 'container2'):?>
<?= $block->getChildChildHtml('options_container') ?>
<?php endif;?>
<?= $block->getChildHtml('form_bottom') ?>
</form>
</div>
<script>
require([
'jquery',
'priceBox'
], function($){
var dataPriceBoxSelector = '[data-role=priceBox]',
dataProductIdSelector = '[data-product-id=<?= $block->escapeHtml($_product->getId()) ?>]',
priceBoxes = $(dataPriceBoxSelector + dataProductIdSelector);
priceBoxes = priceBoxes.filter(function(index, elem){
return !$(elem).find('.price-from').length;
});
priceBoxes.priceBox({'priceConfig': <?= /* @escapeNotVerified */ $block->getJsonConfig() ?>});
});
</script>
Then create app/code/Vendor/Module/etc/frontend/routes.xml
for controller in custom module,
<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:App/etc/routes.xsd">
<router id="standard">
<route frontName="yourfrontname" id="yourfrontname">
<module name="Vendor_Module"/>
</route>
</router>
</config>
Then in controller add the logic,
<?php
namespace Vendor\Module\Controller\Index;
use Magento\Catalog\Model\ProductRepository;
use Magento\Checkout\Model\Cart as CustomerCart;
use Magento\Framework\Data\Form\FormKey;
use Magento\Catalog\Model\ProductFactory;
class YourController extends \Magento\Checkout\Controller\Cart
{
/**
* @param \Magento\Framework\App\Action\Context $context
*/
public function __construct(
ProductRepository $productRepository,
FormKey $formKey,
ProductFactory $product,
\Magento\Framework\App\Action\Context $context,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
\Magento\Checkout\Model\Session $checkoutSession,
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\Data\Form\FormKey\Validator $formKeyValidator,
CustomerCart $cart
) {
parent::__construct(
$context,
$scopeConfig,
$checkoutSession,
$storeManager,
$formKeyValidator,
$cart
);
$this->productRepository = $productRepository;
$this->formKey = $formKey;
$this->product = $product;
}
/**
* Initialize product instance from request data
*
* @return \Magento\Catalog\Model\Product|false
*/
protected function _initProduct()
{
$productId = (int)$this->getRequest()->getParam('product');
if ($productId) {
$storeId = $this->_objectManager->get(
\Magento\Store\Model\StoreManagerInterface::class
)->getStore()->getId();
try {
return $this->productRepository->getById($productId, false, $storeId);
} catch (NoSuchEntityException $e) {
return false;
}
}
return false;
}
/**
* Add product to shopping cart action
*
* @return \Magento\Framework\Controller\Result\Redirect
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
*/
public function execute()
{
$postValues = $this->getRequest()->getPostValue();
$productId = $postValues['product'];
$formKey = $postValues['form_key'];
$qty = $postValues['qty'];
for($qtyVal = 1 ; $qtyVal <= $qty; $qtyVal++) {
try {
$params = array(
'form_key' => $this->formKey->getFormKey(),
'product' => $productId,
'qty' => 1
);
$_product = $this->product->create()->load($productId);
$this->cart->addProduct($_product, $params);
$product = $this->_initProduct();
/**
* @todo remove wishlist observer \Magento\Wishlist\Observer\AddToCart
*/
$this->_eventManager->dispatch(
'checkout_cart_add_product_complete',
['product' => $product, 'request' => $this->getRequest(), 'response' => $this->getResponse()]
);
if (!$this->_checkoutSession->getNoCartRedirect(true)) {
if (!$this->cart->getQuote()->getHasError()) {
$message = __(
'You added %1 to your shopping cart.',
$product->getName()
);
$this->messageManager->addSuccessMessage($message);
}
return $this->goBack(null, $product);
}
} catch(\Exception $e) {
$this->messageManager->addException($e, __('We can\'t add this item to your shopping cart right now.'));
$this->_objectManager->get(\Psr\Log\LoggerInterface::class)->critical($e);
return $this->goBack();
}
}
$this->cart->save();
}
/**
* Resolve response
*
* @param string $backUrl
* @param \Magento\Catalog\Model\Product $product
* @return $this|\Magento\Framework\Controller\Result\Redirect
*/
protected function goBack($backUrl = null, $product = null)
{
if (!$this->getRequest()->isAjax()) {
return parent::_goBack($backUrl);
}
$result = [];
if ($backUrl || $backUrl = $this->getBackUrl()) {
$result['backUrl'] = $backUrl;
} else {
if ($product && !$product->getIsSalable()) {
$result['product'] = [
'statusText' => __('Out of stock')
];
}
}
$this->getResponse()->representJson(
$this->_objectManager->get(\Magento\Framework\Json\Helper\Data::class)->jsonEncode($result)
);
}
}