Magento 2 如何在添加到购物车产品时传递附加数据

Magento 2 how to pass additional data while add to cart product

我在产品详细信息页面中添加了输入字段,需要在没有任何产品属性和新 table 列的情况下与购物车一起保存。 如何做到这一点?

为此,您可以通过使用 event-observer.

来使用 additional_options

请检查我下面的回答。

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" />

由此,您可以在购物车和报价单中添加自定义产品相关值。所以这个值会和订单绑定,会显示在订单数据中。 (后端和前端)