Magento2里循环添加同一个产品到购物车

4.20K 浏览开发笔记

Magento2里循环添加同一个产品到购物车

需要重写 MagentoCheckoutControllerCartAdd

在插件的etc/di.xml里定义

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:nOnamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
<preference for="MagentoCheckoutControllerCartAdd" type="ZouTestRewriteCheckoutControllerCartAdd" />
</config>

ZouTestRewriteCheckoutControllerCartAdd.php 里的核心代码如下:

<?php 
namespace ZouTestRewriteCheckoutControllerCart; 
use MagentoCatalogApiProductRepositoryInterface; 
use MagentoCheckoutModelCart as CustomerCart; 
use MagentoFrameworkExceptionNoSuchEntityException; 
class Add extends MagentoCheckoutControllerCartAdd { 
    public function execute() { 
        .... 
        $productCartInfo = [];             
        //if($params['qty'] > 1 && $product->getTypeId() == GiftCard::TYPE_GIFTCARD_PRODUCT){             
            if($params['qty'] > 1{                 
            //$amGiftcardRecipientNames = array_values($params['am_giftcard_recipient_name']);                 
            $amGiftcardRecipientNames = $params['am_giftcard_recipient_name'];                 
            foreach ($amGiftcardRecipientNames as $name) {                     
                $newParams = $params;                     
                $newParams['am_giftcard_recipient_name'] = $name;                     
                $newParams['qty'] = 1;                     
                //$newParams['giftcard_store_id'] = $email;                     
                $productCartInfo[] = $newParams;                 
            }             
            }else{                 
                $params['am_giftcard_recipient_name'] = current($params['am_giftcard_recipient_name']);                 
                $params['qty'] = 1;                 
                $productCartInfo = [$params];             
            }             
            //print_r($productCartInfo);die;
            //var_dump($params);die;
            foreach ($productCartInfo as $params) {
                $request->setParams($params);
                $product = clone $product;
                //$cart = clone $this->cart;
                $this->_checkoutSession->setGiftcardStoreId($params['giftcard_store_id']);
                $this->cart->addProduct($product, $params);
                // if (!empty($related)) { 
                 //     $this->cart->addProductsByIds(explode(',', $related));
                 // } 
                /**                  
                * @todo remove wishlist observer MagentoWishlistObserverAddToCart
                */ 
                
                $this->_eventManager->dispatch('checkout_cart_add_product_complete',['product' => $product, 'request' => $request, 'response' => $this->getResponse()]);
                //$this->_checkoutSession->resetCheckout();
                }
                $this->cart->save();
              ... 
            } 
       }
  }

重点:

1,需要$product = clone $product;不然的话 自动合并成一个产品了 不是独立分开的

2,$this->cart->save(); 需要在循环外面进行save,不然价格就有问题(除第1个外 其他的价格为0)。

MagentoQuoteModelQuote 里有判断产品是否重复

public function addProduct(
    MagentoCatalogModelProduct $product,
    $request = null,
    $processMode = MagentoCatalogModelProductTypeAbstractType::PROCESS_MODE_FULL
) {
    ...
    $cartCandidates = $product->getTypeInstance()->prepareForCartAdvanced($request, $product, $processMode);
    。。。
    $item = $this->getItemByProduct($candidate);
    if (!$item) {
        $item = $this->itemProcessor->init($candidate, $request);
        $item->setQuote($this);
        $item->setOptions($candidate->getCustomOptions());
        $item->setProduct($candidate);
        // Add only item that is not in quote already
        $this->addItem($item);
    }
}

MagentoQuoteModelQuoteItem里进行比对

public function representProduct($product)     {
    $itemProduct = $this->getProduct();
    if (!$product || $itemProduct->getId() != $product->getId()) {
        return false;
    }
    /**          
    * Check maybe product is planned to be a child of some quote item - in this case we limit search          
    * only within same parent item          
    */         
    $stickWithinParent = $product->getStickWithinParent();         
    if ($stickWithinParent) {             
        if ($this->getParentItem() !== $stickWithinParent) {
            return false;
        }
    }
    // Check options
    $itemOptions = $this->getOptionsByCode();
    $productOptions = $product->getCustomOptions();
    if (!$this->compareOptions($itemOptions, $productOptions)) {
        return false;
    }
    if (!$this->compareOptions($productOptions, $itemOptions)) {
        return false;
    }
    return true;
    
}

只要product的custom options里有不一样的option,就会认为不是同一个产品。

至于如何设置product的custom options,需要在对应产品类型的ProductType里去设置

protected function _prepareProduct(DataObject $buyRequest, $product, $processMode)     {
    。。。
    $product->addCustomOption('am_giftcard_amount', $amount, $product);
}

0