1

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.

enter image description here

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.

enter image description here

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

1

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.

3
  • Let me check it. @Ronak Commented Mar 18, 2020 at 10:07
  • And also run command bin/magento setup:upgrade and bin/magento setup:static-content:deploy -f
    – Ronak
    Commented Mar 18, 2020 at 10:11
  • 1
    It works perfectly. I checked it. Commented Mar 18, 2020 at 10:29
0

I think you forgot $orderItem->save();

1
  • i tried it but its not working. I think problem is with $additionalOptions = $quoteItem->getOptionByCode('additional_options'); Commented Mar 17, 2020 at 9:40
0

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(); 
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.