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" />
由此,您可以在购物车和报价单中添加自定义产品相关值。所以这个值会和订单绑定,会显示在订单数据中。 (后端和前端)
我在产品详细信息页面中添加了输入字段,需要在没有任何产品属性和新 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" />
由此,您可以在购物车和报价单中添加自定义产品相关值。所以这个值会和订单绑定,会显示在订单数据中。 (后端和前端)