I created 4 programmatically custom options. It is successfully display in cart page and also make successful order. I created module for that. Here its code.
path : vendor/addtocart/controller/index/index.php
<?php
namespace Vendor\Addtocart\Controller\Index;
use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\Data\Form\FormKey;
use Magento\Checkout\Model\Cart;
use Magento\Catalog\Model\Product;
use Magento\Framework\View\Result\PageFactory;
class Index extends \Magento\Framework\App\Action\Action
{
 protected $formKey; 
 protected $cart;
 protected $product;
 protected $_pageFactory;
 protected $_session;
 protected $serializer;
 protected $ProductRepository;
 protected $_responseFactory;
 public function __construct(
 \Magento\Framework\App\Action\Context $context,
 \Magento\Framework\Data\Form\FormKey $formKey,
 \Magento\Checkout\Model\Cart $cart,
 \Magento\Catalog\Model\Product $product,
 \Magento\Catalog\Model\ProductRepository $ProductRepository,
 \Magento\Customer\Model\Session $session,
 \Magento\Framework\Serialize\SerializerInterface $serializer,
 \Magento\Framework\View\Result\PageFactory $PageFactory,
 \Magento\Framework\App\ResponseFactory $responseFactory,
 array $data = []) {
 $this->_responseFactory = $responseFactory;
 $this->formKey = $formKey;
 $this->_pageFactory = $PageFactory;
 $this->cart = $cart;
 $this->serializer = $serializer;
 $this->product = $product; 
 $this->ProductRepository = $ProductRepository;
 $this->_session = $session; 
 parent::__construct($context);
 }
 public function execute()
 {
 $page = $this->_pageFactory->create();
 $productId =1;
 $id = $this->_session->getId();
 $additionalOptions['firstnamesku'] = [
 'label' => 'First Name',
 'value' => 'chirag',
 ];
 $additionalOptions['lnamesku'] = [
 'label' => 'Last Name',
 'value' => 'parmar',
 ];
 $additionalOptions['emailidsku'] = [
 'label' => 'Email ID',
 'value' => '[email protected]',
 ];
 $additionalOptions['phonenosku'] = [
 'label' => 'Phone No',
 'value' => '1234567890',
 ];
 if(!$this->_session->isLoggedIn()){
 $params = array(
 'form_key' => $this->formKey->getFormKey(),
 'product' => $productId, //product Id
 'qty' =>1 //quantity of product
 ); 
 }else{
 $params = array(
 'form_key' => $this->formKey->getFormKey(),
 'product' => $productId, //product Id
 'qty' =>1, //quantity of product
 'customer_id' =>$id
 );
 } 
 //Load the product based on productID 
 $_product = $this->ProductRepository->getById($productId);
 $_product->addCustomOption('additional_options', $this->serializer->serialize($additionalOptions)); 
 $this->cart->addProduct($_product, $params);
 $this->cart->save();
 //return $page;
 $message = "Product have been successfully added to your Shopping Cart.";
 $this->messageManager->addSuccess($message);
 $accUrl = $this->_url->getUrl('checkout/cart/');
 $this->_responseFactory->create()->setRedirect($accUrl)->sendResponse();
 $this->setRefererUrl($accUrl);
 }
}
Now I hit this url : domainname.com/addtocart
Successfully add product to cart and redirect to cart page.
Placed order successsfully. Now also seen this order in admin->sales-> orders.
But the problem is I can not find this custom options in order details.
I also created observer for this. But not getting result as I want.
Vendor\Addtocart\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">
 <event name="sales_model_service_quote_submit_before">
 <observer name="unique_name" instance="Vendor\Addtocart\Observer\OrderItemAdditionalOptions" />
 </event>
</config>
Vendor\Addtocart\Observer\OrderItemAdditionalOptions.php
<?php
namespace Vendor\Addtocart\Observer;
use Magento\Framework\Event\ObserverInterface;
class OrderItemAdditionalOptions implements ObserverInterface
{
 /**
 * @param \Magento\Framework\Event\Observer $observer
 */
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
 try {
 $quote = $observer->getQuote();
 $order = $observer->getOrder();
 $quoteItems = [];
 // Map Quote Item with Quote Item Id
 foreach ($quote->getAllVisibleItems() as $quoteItem) {
 $quoteItems[$quoteItem->getId()] = $quoteItem;
 }
 foreach ($order->getAllVisibleItems() as $orderItem) {
 $quoteItemId = $orderItem->getQuoteItemId();
 $quoteItem = $quoteItems[$quoteItemId];
 $additionalOptions = $quoteItem->getOptionByCode('additional_options');
 //print_r($additionalOptions); exit("=======");
 if (count($additionalOptions) > 0) {
 // Get Order Item's other options
 $options = $orderItem->getProductOptions();
 // Set additional options to Order Item
 $options['additional_options'] = unserialize($additionalOptions->getValue());
 $orderItem->setProductOptions($options);
 }
 }
 } catch (\Exception $e) {
 // catch error if any
 echo 'Error!!: ' .$e->getMessage();
 }
 }
}
I got error in this code. This code is just for information.
Anyone can help me to figured it out? Thanks in advance..
Edit:-
I saw that in database table "sales_order_item" fieldname "product_options"has this value :
{"info_buyRequest":{"product":1,"qty":1}}
Now I create 2 custom option from adminside and check database for other product. I got following code. If I put this code in that order, than it will give some data which i want :
{"info_buyRequest":{"uenc":"aHR0cDovLzEyNy4wLjAuMS9tMjM0L3N0cml2ZS1zaG91bGRlci1wYWNrLmh0bWw,","product":"2","selected_configurable_option":"","related_product":"","item":"2","options":{"1":"cparmar2","2":"rkhatri2"},"qty":"1"},"options":[{"label":"colorbox","value":"cparmar2","print_value":"cparmar2","option_id":"1","option_type":"field","option_value":"cparmar2","custom_view":false},{"label":"sizebox","value":"rkhatri2","print_value":"rkhatri2","option_id":"2","option_type":"field","option_value":"rkhatri2","custom_view":false}]}
3 Answers 3
Please try below code
create Event: Vendor\Addtocart\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">
 <event name="sales_model_service_quote_submit_before">
 <observer name="quote_to_order" instance="Vendor\Addtocart\Observer\OrderItemAdditionalOptions" />
 </event>
</config>
and then create observer like this
Vendor\Addtocart\Observer\OrderItemAdditionalOptions.php
<?php
namespace Vendor\Addtocart\Observer;
use Magento\Framework\Event\ObserverInterface;
use \Magento\Framework\Unserialize\Unserialize;
use \Magento\Framework\Serialize\Serializer\Json;
class OrderItemAdditionalOptions implements ObserverInterface
{
 /**
 * @param \Magento\Framework\Event\Observer $observer
 */
 protected $Unserialize;
 protected $Serializer;
 public function __construct(
 Unserialize $Unserialize,
 Json $Json
 ){
 $this->Unserialize = $Unserialize;
 $this->Serializer = $Json;
 }
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
 try {
 $quote = $observer->getQuote();
 $order = $observer->getOrder();
 $quoteItems = [];
 // Map Quote Item with Quote Item Id
 foreach ($quote->getAllVisibleItems() as $quoteItem) {
 $quoteItems[$quoteItem->getId()] = $quoteItem; //130
 }
 foreach ($order->getAllVisibleItems() as $orderItem) {
 $quoteItemId = $orderItem->getQuoteItemId();
 $quoteItem = $quoteItems[$quoteItemId];
 $additionalOptions = $quoteItem->getOptionByCode('additional_options');
 // Get Order Item's other options
 $options = $orderItem->getProductOptions();
 // Set additional options to Order Item
 if($this->isSerialized($additionalOptions->getValue())){
 $options['options'] = $this->Unserialize->unserialize($additionalOptions->getValue());
 }else{
 $options['options'] = $this->Serializer->unserialize($additionalOptions->getValue());
 }
 $orderItem->setProductOptions($options);
 }
 }
 catch (\Exception $e) {
 // catch error if any
 $e->getMessage();
 }
 }
 private function isSerialized($value)
 {
 return (boolean) preg_match('/^((s|i|d|b|a|O|C):|N;)/', $value);
 }
}
?>
Hope this will help you. If it works please accept it.
- 
 Let me check it. @RonakChirag Parmar– Chirag Parmar2020年03月18日 10:07:20 +00:00Commented Mar 18, 2020 at 10:07
- 
 And also run command bin/magento setup:upgrade and bin/magento setup:static-content:deploy -fRonak– Ronak2020年03月18日 10:11:33 +00:00Commented Mar 18, 2020 at 10:11
- 
 1It works perfectly. I checked it.Chirag Parmar– Chirag Parmar2020年03月18日 10:29:34 +00:00Commented Mar 18, 2020 at 10:29
I think you forgot $orderItem->save();
- 
 i tried it but its not working. I think problem is with $additionalOptions = $quoteItem->getOptionByCode('additional_options');Chirag Parmar– Chirag Parmar2020年03月17日 09:40:20 +00:00Commented Mar 17, 2020 at 9:40
It will append option into the column(product_options) of table (sales_order_item) and it will show in admin,email and pdf.
$orderItems = $order->getAllItems();
$serialNo = 123456;
foreach($orderItems as $orderItem){
 $orderItemId = $orderItem->getItemId();
 $option = $orderItem->getProductOptions();
 $serialOptions[] = array('label' => "Serial No.",'value' => $serialNo);
 $option['options'] = $serialOptions;
 $orderItem->setProductOptions($option)->save(); 
}
Explore related questions
See similar questions with these tags.