如何以编程方式将产品添加到购物车
在本文中,我们将向您展示如何在 Magento 2 中以编程方式将产品添加到购物车。这在您想要向购物车中的商品添加额外数据、添加需要自定义逻辑的产品或只是为购物车添加礼物时最有用。购买您的产品的客户。
本文假设:
- 我们正在将代码添加到名为 Magenest\Example 的自定义模块中,路径为“example”
- 自定义添加到购物车功能在 Magenest\Example\Controller\Product 的控制器中执行
如何使用报价模型将产品添加到购物车
控制器 AddToCart 处理发送到路径“example/product/addToCart”的 GET 请求,并使用存储在请求参数中的信息将产品添加到购物车。
<?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。
如何使用其他选项将产品添加到购物车
addProduct 函数可以适应简单参数格式和高级参数格式。这允许您向购物车项目添加其他选项和数据。
/** * @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(); }
Product 的“additional_options”将显示在购物车页面上:
购物车页面上的产品附加选项
如何将特殊类型的产品添加到购物车
将一些具有特殊类型的产品添加到购物车可能需要提供额外的选项。假设您知道所需的具体参数值,您还可以将这些产品添加到购物车中。以下是将捆绑产品添加到购物车的一般格式:
/** * @throws LocalizedException */ public function addSpecialProduct() { $productId = $this->getRequest()->getParam('id'); $product = $this->productRepository->getById($productId); $buyRequest = new \Magento\Framework\DataObject([ // super_group 用于设置分组产品中子项目的数量 'super_group' => [ 10 => "1", // value is pass as $sub-productId => $qty 20 => "2" ], // 添加捆绑产品需要两个选项:'bundle_option' 和 'bundle_option_qty' // 两个选项都作为索引数组传递, 'bundle_option' => ["2", "4", "5"], // 使用捆绑产品 'selection_id' 添加项目,而不是实际产品 ID 'bundle_option_qty' => ["1", "2", " 3"], // 可配置的产品选项使用 'super_attribute' 传递 option 'super_attribute' => [ 143 => "168", // 格式为 $optionId => $optionValue 93 => "58" ] ]); $session = $this->checkoutSession->create(); $quote = $session->getQuote(); $quote->addProduct($product, $buyRequest); $this->cartRepository->save($quote); $session->replaceQuote($quote)->unsLastRealOrderId(); }
每种特殊产品类型都有自己的功能来获取特殊属性。请参阅这些产品的类型模型以了解如何手动添加它们。
例如,可以使用函数 getConfigurableAttributes() 或 getConfigurableAttributesAsArray() 提取可配置产品属性。这使我们可以使用其简单的 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:
可配置产品的可配置 SKU
以编程方式添加到购物车时触发迷你购物车更新
与每次访问时都请求最新数据的购物车页面不同,迷你购物车内容使用 Magento 的 customer-data.js 库缓存在客户端。
这个缓存只能通过在客户端机器上执行Javascript来清除;因为服务器通常不能请求清除客户端上保存的数据。因此,customer-data.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 允许使用sections.xml 配置文件来配置这些端点服务器端:
Magenest/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 请求都将触发重新加载“购物车”数据,而无需手动向 AJAX 请求添加回调。