Magento 2 Programatically add product to cart with additional options
Question
I want to add product to cart with some additional data. My code adds the product to cart,but the additional info is not saved properly.
I want to display the additional content in cart like custom option
http://i.prntscr.com/KzmHQqaNSYGhOt3buzlK1A.png
Here is my code
namespace Namespace\Module\Controller\Index;
use Magento\Framework\View\Result\PageFactory;
use Magento\Framework\App\Action\Context;
class Post extends \Magento\Framework\App\Action\Action
{
protected $resultPageFactory;
protected $_productRepository;
protected $_cart;
protected $formKey;
private $serializer;
public function __construct(
Context $context,
\Magento\Catalog\Model\ProductRepository $productRepository,
\Magento\Checkout\Model\Cart $cart,
\Magento\Framework\Data\Form\FormKey $formKey,
\Magento\Framework\Serialize\SerializerInterface $serializer,
PageFactory $resultPageFactory
) {
$this->resultPageFactory = $resultPageFactory;
$this->_productRepository = $productRepository;
$this->_cart = $cart;
$this->formKey = $formKey;
$this->serializer = $serializer;
parent::__construct($context);
}
public function execute()
{
$post = $this->getRequest()->getPostValue();
$additionalOptions['print_style'] = [
'label' => 'Print Style',
'value' => 'Test',
];
$params = array(
'product' => 4,
'qty' => 1,
'options' => array('additional_options'=>$this->serializer->serialize($additionalOptions))
);
$_product = $this->_productRepository->getById(4);
$this->_cart->addProduct($_product,$params);
$this->_cart->save();
echo 'success';
}
}
How can I do it?
Solution
The following code works.
http://i.prntscr.com/cFUE8nuRQC2Veg4i3xo9OQ.png
$productId = 4;
$additionalOptions['print_style'] = [
'label' => 'Print Style',
'value' => 'Test'
];
$params = array(
'product' => $productId,
'qty' => 1
);
$_product = $this->_productRepository->getById($productId);
$_product->addCustomOption('additional_options', $this->serializer->serialize($additionalOptions));
$this->_cart->addProduct($_product, $params);
$this->_cart->save();
OTHER TIPS
You need to use Observer checkout_cart_product_add_after to add custom data in additional_options
Here is full Example
You may use 2 approaches here
1) You may use setOptions()
method to set the custom options before adding product to cart
Your approach will be like
$customOptionFactory = $objectManager->create('Magento\Catalog\Api\Data\ProductCustomOptionInterfaceFactory');
$additionalOptions['print_style'] = [
'label' => 'Print Style',
'value' => 'Test',
];
$customOptions = [];
foreach ($additionalOptions['print_style'] as $option) {
$customOption = $customOptionFactory->create(['data' => $option]);
$customOption->setProductSku($_product->getSku());
$customOptions[] = $customOption;
}
$_product->setOptions($customOptions);
$this->_cart->addProduct($_product,$params);
$this->_cart->save();
for this approach you may take dev/tests/integration/testsuite/Magento/Catalog/_files/product_with_options.php
as reference
2) You may use addCustomOption()
method on $_product
In this case your approach will be
$additionalOptions['print_style'] = [
'label' => 'Print Style',
'value' => 'Test',
];
$_product->addCustomOption('additional_options',serialize($additionalOptions));
P.S. Just in case you're curious to know how addCustomOption()
is working , take a quick look on file
vendor/magento/module-catalog/Model/Product.php
This can be implemented using the event observer. You can add following files in your module Namespace/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">
<event name="checkout_cart_product_add_after">
<observer name="namespace_module_checkout_cart_product_add_after" instance="Namespace\Module\Observer\CheckoutCartProductAddAfterObserver" />
</event>
</config>
Namespace/Module/Observer/CheckoutCartProductAddAfterObserver.php
namespace Namespace\Module\Observer;
use Magento\Framework\Event\Observer as EventObserver;
use Magento\Framework\Event\ObserverInterface;
use Magento\Framework\App\RequestInterface;
class CheckoutCartProductAddAfterObserver implements ObserverInterface {
protected $_request;
public function __construct(RequestInterface $request) {
$this->_request = $request;
}
public function execute(EventObserver $observer) {
$item = $observer->getQuoteItem();
$additionalOptions = array();
if ($additionalOption = $item->getOptionByCode('additional_options')) {
$additionalOptions = (array) unserialize($additionalOption->getValue());
}
// $post = $this->_request->getParam('print_style'); // Your data added here
$post = array('Print Style' = > 'Test');
if (is_array($post)) {
foreach ($post as $key => $value) {
if ($key == '' || $value == '') {
continue;
}
$additionalOptions[] = array(
'label' => $key,
'value' => $value
);
}
}
if (count($additionalOptions) > 0) {
$item->addOption(array(
'product_id' => $item->getProductId(),
'code' => 'additional_options',
'value' => serialize($additionalOptions)
));
}
}
}
Hope this will help you.
If the method "$this->serializer->serialize" not works then
use json_encode instead of serializer method.
This code works here : add products to cart with customizable options
$product = $productFactory->create();
$product->setStoreId(1)->load($product->getIdBySku($sku));
$params = new \Magento\Framework\DataObject();
$params->setQty($qty);
foreach ($product->getOptions() as $o) {
foreach ($o->getValues() as $value) {
if ($value["sku"] == 'RED') { //add this if to search for your custom option by sku or the value name etc.
$options[$value['option_id']] = $value['option_type_ id'];
$params->setOptions($options); //set the customizable option to the product
}
}
}
try {
$quote1->addProduct($product, $params); //add to cart 🙂
} catch (Exception $e) {echo $e->getMessage();}