Magento2 如何往购物车添加商品

在本文中,我们将向您展示如何在Magento 2中以编程方式将产品添加到购物车中。当您想向购物车中的项目添加其他数据、添加需要自定义逻辑的产品或只是为购买您产品的客户添加礼物时,这是最有用的

使用Quote Model往购物车添加商品

controller

<?php
namespace Magenest\Example\Controller\Product;

use Magento\Framework\App\Action\Action;
use Magento\Framework\App\Action\Context;
use Magento\Framework\App\Action\HttpGetActionInterface;
use Magento\Framework\Controller\ResultInterface;
use Magento\Framework\Exception\LocalizedException;

/**
* Class AddToCart
* @package Magenest\BookingReservation\Controller\Product
*/
class AddToCart extends Action implements HttpGetActionInterface
{
   /** @var \Magento\Checkout\Model\SessionFactory */
   private $checkoutSession;

   /** @var \Magento\Quote\Api\CartRepositoryInterface */
   private $cartRepository;

   /** @var \Magento\Catalog\Api\ProductRepositoryInterface */
   private $productRepository;

   /** @var \Magento\Framework\Serialize\Serializer\Json */
   private $json;

   /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable */
   private $configurableType;

   /**
     * AddToCart constructor.
     * @param Context $context
     * @param \Magento\Framework\Serialize\Serializer\Json $json
     * @param \Magento\Checkout\Model\SessionFactory $checkoutSession
     * @param \Magento\Quote\Api\CartRepositoryInterface $cartRepository
     * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
     * @param \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType
     */
   public function __construct(
       Context $context,
       \Magento\Framework\Serialize\Serializer\Json $json,
       \Magento\Checkout\Model\SessionFactory $checkoutSession,
       \Magento\Quote\Api\CartRepositoryInterface $cartRepository,
       \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
       \Magento\ConfigurableProduct\Model\Product\Type\Configurable $configurableType
   ) {
       $this->checkoutSession = $checkoutSession;
       $this->cartRepository = $cartRepository;
       $this->productRepository = $productRepository;
       $this->json = $json;
       $this->configurableType = $configurableType;
       parent::__construct($context);
   }

   /**
    * @return ResultInterface
    * @throws LocalizedException
    */
   public function execute()
   {
       $product = $this->productRepository->getById($this->getRequest()->getParam('id'));
       $qty = $this->getRequest()->getParam('qty');

       $session = $this->checkoutSession->create();
       $quote = $session->getQuote();
       $quote->addProduct($product, $qty);

       $this->cartRepository->save($quote);
       $session->replaceQuote($quote)->unsLastRealOrderId();
   }
}

您可以仅使用产品ID将产品添加到购物车。数量参数是可选的:如果参数为空,报价模型将假定数量为1

添加带有Custom Option的购物车

/**
* @throws LocalizedException
*/
public function addProductWithOptions()
{
   $productSku = $this->getRequest()->getParam('sku');
   $qty       = $this->getRequest()->getParam('qty');

   /**
    * You can specify custom options for a product before adding it to cart
    */
   $product = $this->productRepository->get($productSku);
   $product->addCustomOption('additional_options', $this->json->serialize([
       'custom_option_1' => [
           'label' => __("Custom Option 1"),
           'value' => 10
       ],
       'custom_option_2' => [
           'label' => __("Custom Option 2"),
           'value' => 20
       ]
   ]));

   /**
    * The second parameter of addProduct function can either be an integer, or a Magento DataObject
    * An integer will be interpreted as quantity added
    * Using a DataObject will allow adding custom data to cart items; these data will be saved and can be retrieved as info_buyRequest of quote/order items
    */
   $buyRequest = new \Magento\Framework\DataObject([
       'qty' => $qty,
       'related_product' => '',
       'custom_option' => '?'
   ]);

   $session = $this->checkoutSession->create();
   $quote = $session->getQuote();
   $quote->addProduct($product, $buyRequest);

   $this->cartRepository->save($quote);
   $session->replaceQuote($quote)->unsLastRealOrderId();
}

购物车页面会显示Custom Option


image.png

将特殊类型的产品添加到购物车

将某些特殊类型的产品添加到购物车可能需要提供其他选项。假设您知道所需的特定参数值,也可以将这些产品添加到购物车中。以下是将捆绑产品添加到购物车的一般格式

/**
* @throws LocalizedException
*/
public function addSpecialProduct()
{
   $productId = $this->getRequest()->getParam('id');
   $product = $this->productRepository->getById($productId);

   $buyRequest = new \Magento\Framework\DataObject([
       // super_group is used to set quantity for sub-items in grouped product
       'super_group' => [
           10 => "1", // value is pass as $sub-productId => $qty
           20 => "2"
       ],

       // adding bundle product require two options: 'bundle_option' and 'bundle_option_qty'
       // both options are passed as indexed array, and items in two array will be matched using their index
       'bundle_option'     => ["2", "4", "5"], // items are added using bundle product 'selection_id', not actual product id
       'bundle_option_qty' => ["1", "2", "3"],

       // configurable product options are passed using 'super_attribute' option
       'super_attribute' => [
           143 => "168", // the format are $optionId => $optionValue
           93 => "58"
       ]
   ]);

   $session = $this->checkoutSession->create();
   $quote = $session->getQuote();
   $quote->addProduct($product, $buyRequest);

   $this->cartRepository->save($quote);
   $session->replaceQuote($quote)->unsLastRealOrderId();
}

每个特殊产品类型都有自己的函数来获取特殊属性。请参阅这些产品的类型模型,以了解如何手动添加它们。

例如,可以使用函数getConfigurableAttributes()或getConfiguraableAttributesAsArray()提取可配置产品属性。这允许我们使用简单的SKU将可配置产品添加到购物车中:

/**
* @throws LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
private function addConfigurableProduct()
{
   $childId = $this->getRequest()->getParam('id');
   $childProduct = $this->productRepository->getById($childId);

   /** @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable configurableType */
   $parentId = $this->configurableType->getParentIdsByChild($childId);
   if (($parentId = reset($parentId)) !== false) {
       $parentProduct = $this->productRepository->getById($parentId);
       $productAttributeOptions = $this->configurableType->getConfigurableAttributesAsArray($parentProduct);

       $options = [];
       foreach ($productAttributeOptions as $option) {
           $options[$option['attribute_id']] =  $childProduct->getData($option['attribute_code']);
       }
       $buyRequest = new \Magento\Framework\DataObject(['super_attribute' => $options]);

       $session = $this->checkoutSession->create();
       $quote = $session->getQuote();
       $quote->addProduct($parentProduct, $buyRequest);

       $this->cartRepository->save($quote);
       $session->replaceQuote($quote)->unsLastRealOrderId();
   }
}

应始终将可配置产品添加为具有自定义选项的可配置SKU,而不是简单的SKU:


image.png

迷你购物车更新

与每次访问时都请求最新数据的购物车页面不同,迷你购物车内容使用Magento的客户数据缓存在客户端。js库。
此缓存只能通过在客户端机器上执行Javascript来清除;因为服务器通常无法请求清除保存在客户端上的数据。因此,对客户数据进行缓存失效和重新加载。js通常发生在客户端触发事件时,如成功的AJAX请求。

可以将迷你购物车配置为在完成对addToCart端点的AJAX请求时进行更新:

require([
   'jquery',
   'mage/url',
   'Magento_Customer/js/customer-data'
], function ($, urlBuilder, customerData) {
   $.ajax({
       type: 'POST',
       data: {
           product_id: ...,
           qty: ...
       },
       url: urlBuilder.build('example/product/addToCart'),
       complete: function () {
           // you might not need this section if you're using sections.xml instead
           customerData.invalidate(['cart']);
           customerData.reload(['cart'], true);
       },
       success: ...,
       error: ...
   })
});

然而,每次直接调用这些函数并不是很有效。Magento允许使用节配置这些端点服务器端。改为xml配置文件:
Example/etc/frontend/sections.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Customer:etc/sections.xsd">
   <action name="example/product/addToCart">
       <section name="cart"/>
   </action>
</config>

现在,所有使用Magento 2 AJAX库发送到“example/product/addToCart”的AJAX请求都将触发重新加载“cart”数据,而无需手动向AJAX申请添加回调。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容