I have added input field in product detail page and need to save with cart without any product attribute and new table column. How to do this?
To do this, you can use additional_options by using event-observer.
Please check my below answer.
events.xml : app\code\Vendor\Module\etc\events.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
<!-- add option with quote item when add to cart -->
<event name="checkout_cart_product_add_after">
<observer name="pf_checkout_cart_product_add_after" instance="Vendor\Module\Observer\CheckoutCartAddObserver" />
</event>
<!-- add option with quote item with ORDER -->
<event name="sales_model_service_quote_submit_before">
<observer name="pf_sales_model_service_quote_submit_before" instance="Vendor\Module\Observer\QuoteSubmitObserver" />
</event>
</config>
CheckoutCartAddObserver: app\code\Vendor\Module\Observer\CheckoutCartAddObserver.php
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
/**
* CheckoutCartAddObserver
*/
class CheckoutCartAddObserver implements ObserverInterface
{
protected $_layout;
protected $_storeManager;
protected $_request;
/**
* __construct
*
* @param \Magento\Store\Model\StoreManagerInterface storeManager
* @param \Magento\Framework\View\LayoutInterface layout
* @param \Magento\Framework\App\RequestInterface request
* @param \Magento\Framework\Serialize\SerializerInterface serializer
*
*/
public function __construct(
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\View\LayoutInterface $layout,
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\Serialize\SerializerInterface $serializer
) {
$this->_layout = $layout;
$this->_storeManager = $storeManager;
$this->_request = $request;
$this->serializer = $serializer;
}
/**
* execute
*
* @param EventObserver observer
*
* @return void
*/
public function execute(EventObserver $observer)
{
$postValue = $this->_request->getParams();
// product_color_shade is input field in product view page
if (isset($postValue['product_color_shade']) &&
$postValue['product_color_shade']) {
$item = $observer->getQuoteItem();
$colorShade = [];
$colorShade[] = [
'label' => 'Color Shade',
'value' => $postValue['product_color_shade'],
];
if (count($colorShade) > 0) {
$item->addOption([
'product_id' => $item->getProductId(),
'code' => 'additional_options',
'value' => $this->serializer->serialize($colorShade),
]);
}
}
}
}
QuoteSubmitObserver: app\code\Vendor\Module\Observer\QuoteSubmitObserver.php
<?php
namespace Vendor\Module\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
/**
* QuoteSubmitObserver
*/
class QuoteSubmitObserver implements ObserverInterface
{
private $quoteItems = [];
private $quote = null;
private $order = null;
/**
* __construct
*
* @param \Magento\Store\Model\StoreManagerInterface storeManager
* @param \Magento\Framework\View\LayoutInterface layout
* @param \Magento\Framework\App\RequestInterface request
* @param \Magento\Framework\Serialize\SerializerInterface serializer
*
*/
public function __construct(
\Magento\Store\Model\StoreManagerInterface $storeManager,
\Magento\Framework\View\LayoutInterface $layout,
\Magento\Framework\App\RequestInterface $request,
\Magento\Framework\Serialize\SerializerInterface $serializer
) {
$this->_layout = $layout;
$this->_storeManager = $storeManager;
$this->_request = $request;
$this->serializer = $serializer;
}
/**
* execute
*
* @param EventObserver observer
*
* @return void
*/
public function execute(EventObserver $observer)
{
$this->quote = $observer->getQuote();
$this->order = $observer->getOrder();
foreach ($this->order->getItems() as $orderItem) {
if ($quoteItem = $this->getQuoteItemById($orderItem->getQuoteItemId())) {
if ($additionalOptionsQuote = $quoteItem->getOptionByCode('additional_options')) {
if ($additionalOptionsOrder = $orderItem->getProductOptionByCode('additional_options')) {
$additionalOptions = array_merge($additionalOptionsQuote, $additionalOptionsOrder);
} else {
$additionalOptions = $additionalOptionsQuote;
}
if (count($additionalOptions->getData()) > 0) {
$options = $orderItem->getProductOptions();
$options['additional_options'] = $this->serializer->unserialize($additionalOptions->getValue());
$orderItem->setProductOptions($options);
}
}
}
}
}
/**
* getQuoteItemById
*
* @param mixed id
*
* @return void
*/
private function getQuoteItemById($id)
{
if (empty($this->quoteItems)) {
if ($this->quote->getItems()) {
foreach ($this->quote->getItems() as $item) {
$this->quoteItems[$item->getId()] = $item;
}
}
}
if (array_key_exists($id, $this->quoteItems)) {
return $this->quoteItems[$id];
}
return null;
}
}
catalog_product_view.xml: app\code\Vendor\Module\view\frontend\layout\catalog_product_view.xml
<?xml version="1.0"?>
<page layout="1column" 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.form.content">
<block class="Magento\Catalog\Block\Product\View" name="color.shade" template="Vendor_Module::color_shade.phtml" before="product.info.addtocart" />
</referenceContainer>
</body>
</page>
color_shade.phtml :app\code\Vendor\Module\view\frontend\templates\color_shade.phtml
<input type="text" name="product_color_shade" id="product_color_shade" />
By this, you can add your custom product related values in cart and also in quote. So this value will bind with order and will display in order data. (Backend and Frontend)