Woocommerce多商品带附加组件的URL添加购物车方案问询
问题描述
我用ChatGPT编写了一款WooCommerce插件,支持通过URL将带附加组件的商品加入外部购物车,但目前仅支持单个商品。我需要扩展功能,实现多个带不同附加组件的商品通过URL批量加入购物车。
现有单商品URL结构
https://example.local:8890/example/basket/?add-to-cart=1099&quantity=1&size=16%20(2-3yrs)&shirt_name=MESSI&shirt_number=10&add_matching_socks=true&add_league_patches_to_arms=true
现有插件代码
<?php /** * Plugin Name: Custom Add to Cart * Description: Adds support for adding multiple products with quantities to the cart via URL. * Version: 1.0 * Author: Chris / ChatGPT * Author URI: https://example.com/ * Text Domain: custom-add-to-cart * Domain Path: /languages */ function webroom_modify_cart_data($cart_item_data, $product_id, $variation_id, $quantity) { // Process add-ons $addons = array(); if (isset($_REQUEST['size'])) { $addons['size'] = sanitize_text_field($_REQUEST['size']); } if (isset($_REQUEST['shirt_name'])) { $addons['shirt_name'] = sanitize_text_field($_REQUEST['shirt_name']); } if (isset($_REQUEST['shirt_number'])) { $addons['shirt_number'] = sanitize_text_field($_REQUEST['shirt_number']); } if (isset($_REQUEST['add_matching_socks'])) { $addons['add_matching_socks'] = filter_var($_REQUEST['add_matching_socks'], FILTER_VALIDATE_BOOLEAN); } if (isset($_REQUEST['add_league_patches_to_arms'])) { $addons['add_league_patches_to_arms'] = filter_var($_REQUEST['add_league_patches_to_arms'], FILTER_VALIDATE_BOOLEAN); } // Add add-ons as cart item data foreach ($addons as $addon_name => $addon_value) { $cart_item_data["webroom_{$addon_name}"] = $addon_value; } return $cart_item_data; } add_filter('woocommerce_add_cart_item_data', 'webroom_modify_cart_data', 10, 4); function webroom_get_cart_item_from_session($cart_item, $values) { // Add add-ons from session data to cart item if (is_array($values)) { foreach ($values as $key => $value) { if (strpos($key, 'webroom_') === 0) { $cart_item[$key] = $value; } } } return $cart_item; } add_filter('woocommerce_get_cart_item_from_session', 'webroom_get_cart_item_from_session', 20, 2); function webroom_add_cart_item_data($item_data, $cart_item) { // Add custom data to cart item display foreach ($cart_item as $key => $value) { if (strpos($key, 'webroom_') === 0) { if ($key === 'webroom_add_matching_socks') { $value = $value ? '(+£3.49)' : ''; } elseif ($key === 'webroom_add_league_patches_to_arms') { $value = $value ? '(+£1.99)' : ''; } $item_data[] = array( 'name' => str_replace('_', ' ', substr($key, 8)), 'value' => $value ); } } return $item_data; } add_filter('woocommerce_get_item_data', 'webroom_add_cart_item_data', 10, 2); function webroom_calculate_cart_totals($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } foreach ($cart->get_cart() as $cart_item_key => $cart_item) { // Check if the cart item was added via URL or manually $added_via_url = isset($cart_item['webroom_size']) && isset($cart_item['webroom_shirt_name']); // Get the product price based on how it was added to the cart if ($added_via_url) { $product = wc_get_product($cart_item['product_id']); $product_price = $product->get_price(); } else { $product = $cart_item['data']; $product_price = $cart_item['line_subtotal'] / $cart_item['quantity']; } // Calculate add-ons cost $add_ons_cost = 0; if (isset($cart_item['webroom_add_matching_socks']) && $cart_item['webroom_add_matching_socks']) { $add_ons_cost += 3.49; } if (isset($cart_item['webroom_add_league_patches_to_arms']) && $cart_item['webroom_add_league_patches_to_arms']) { $add_ons_cost += 1.99; } // Calculate item subtotal and total based on add-ons $item_subtotal = $product_price + $add_ons_cost; $item_total = $item_subtotal * $cart_item['quantity']; // Update cart item data with new totals $cart_item['data']->set_price($item_subtotal); $cart_item['line_subtotal'] = $item_subtotal; $cart_item['line_total'] = $item_total; // Save updated data back to the cart $cart->cart_contents[$cart_item_key] = $cart_item; } } add_action('woocommerce_calculate_totals', 'webroom_calculate_cart_totals');
附加组件说明
size:16 (2-3yrs) shirt name:MESSI shirt number:10 add matching socks:(+£3.49) add league patches to arms:(+£1.99)
技术需求
需要构造包含多个商品的URL(比如另一个商品:球衣名KANE、号码9,其他附加组件可自定义),并修改插件代码以支持批量处理这些商品,实现多商品带附加组件加入购物车。
解决方案
1. 多商品URL构造规则
采用数组式参数命名,每个商品的参数通过索引区分(从0开始):
- 商品ID:
add-to-cart[0]=1099、add-to-cart[1]=1099(同一款商品ID可重复) - 数量:
quantity[0]=1、quantity[1]=1 - 附加组件:
size[0]=16%20(2-3yrs)、shirt_name[0]=MESSI;size[1]=18%20(4-5yrs)、shirt_name[1]=KANE
示例URL
https://example.local:8890/example/basket/?add-to-cart[0]=1099&quantity[0]=1&size[0]=16%20(2-3yrs)&shirt_name[0]=MESSI&shirt_number[0]=10&add_matching_socks[0]=true&add_league_patches_to_arms[0]=true&add-to-cart[1]=1099&quantity[1]=1&size[1]=18%20(4-5yrs)&shirt_name[1]=KANE&shirt_number[1]=9&add_matching_socks[1]=false&add_league_patches_to_arms[1]=true
2. 插件代码修改
替换原有的webroom_modify_cart_data函数,新增批量处理逻辑,其他函数保持不变:
修改后的完整插件代码
<?php /** * Plugin Name: Custom Add to Cart * Description: Adds support for adding multiple products with quantities to the cart via URL. * Version: 2.0 * Author: Chris / ChatGPT * Text Domain: custom-add-to-cart * Domain Path: /languages */ // 批量处理多商品添加请求 function webroom_handle_multiple_add_to_cart() { if (isset($_REQUEST['add-to-cart']) && is_array($_REQUEST['add-to-cart'])) { foreach ($_REQUEST['add-to-cart'] as $index => $product_id) { $product_id = sanitize_text_field($product_id); $quantity = isset($_REQUEST['quantity'][$index]) ? absint($_REQUEST['quantity'][$index]) : 1; // 收集当前商品的附加组件 $addons = []; $addon_fields = ['size', 'shirt_name', 'shirt_number', 'add_matching_socks', 'add_league_patches_to_arms']; foreach ($addon_fields as $field) { if (isset($_REQUEST[$field][$index])) { if (in_array($field, ['add_matching_socks', 'add_league_patches_to_arms'])) { $addons[$field] = filter_var($_REQUEST[$field][$index], FILTER_VALIDATE_BOOLEAN); } else { $addons[$field] = sanitize_text_field($_REQUEST[$field][$index]); } } } // 添加商品到购物车,并传递附加组件数据 $cart_item_data = []; foreach ($addons as $addon_name => $addon_value) { $cart_item_data["webroom_{$addon_name}"] = $addon_value; } WC()->cart->add_to_cart($product_id, $quantity, 0, [], $cart_item_data); } // 重定向到购物车页面(可选,根据需求调整) wp_redirect(wc_get_cart_url()); exit; } } add_action('template_redirect', 'webroom_handle_multiple_add_to_cart'); function webroom_get_cart_item_from_session($cart_item, $values) { // Add add-ons from session data to cart item if (is_array($values)) { foreach ($values as $key => $value) { if (strpos($key, 'webroom_') === 0) { $cart_item[$key] = $value; } } } return $cart_item; } add_filter('woocommerce_get_cart_item_from_session', 'webroom_get_cart_item_from_session', 20, 2); function webroom_add_cart_item_data($item_data, $cart_item) { // Add custom data to cart item display foreach ($cart_item as $key => $value) { if (strpos($key, 'webroom_') === 0) { if ($key === 'webroom_add_matching_socks') { $value = $value ? '(+£3.49)' : ''; } elseif ($key === 'webroom_add_league_patches_to_arms') { $value = $value ? '(+£1.99)' : ''; } $item_data[] = array( 'name' => str_replace('_', ' ', substr($key, 8)), 'value' => $value ); } } return $item_data; } add_filter('woocommerce_get_item_data', 'webroom_add_cart_item_data', 10, 2); function webroom_calculate_cart_totals($cart) { if (is_admin() && !defined('DOING_AJAX')) { return; } foreach ($cart->get_cart() as $cart_item_key => $cart_item) { // Check if the cart item was added via URL or manually $added_via_url = isset($cart_item['webroom_size']) && isset($cart_item['webroom_shirt_name']); // Get the product price based on how it was added to the cart if ($added_via_url) { $product = wc_get_product($cart_item['product_id']); $product_price = $product->get_price(); } else { $product = $cart_item['data']; $product_price = $cart_item['line_subtotal'] / $cart_item['quantity']; } // Calculate add-ons cost $add_ons_cost = 0; if (isset($cart_item['webroom_add_matching_socks']) && $cart_item['webroom_add_matching_socks']) { $add_ons_cost += 3.49; } if (isset($cart_item['webroom_add_league_patches_to_arms']) && $cart_item['webroom_add_league_patches_to_arms']) { $add_ons_cost += 1.99; } // Calculate item subtotal and total based on add-ons $item_subtotal = $product_price + $add_ons_cost; $item_total = $item_subtotal * $cart_item['quantity']; // Update cart item data with new totals $cart_item['data']->set_price($item_subtotal); $cart_item['line_subtotal'] = $item_subtotal; $cart_item['line_total'] = $item_total; // Save updated data back to the cart $cart->cart_contents[$cart_item_key] = $cart_item; } } add_action('woocommerce_calculate_totals', 'webroom_calculate_cart_totals');
代码修改说明
新增
webroom_handle_multiple_add_to_cart函数:- 检测URL中的数组形式参数
add-to-cart,遍历每个商品索引 - 按索引收集对应商品的数量和附加组件参数
- 调用
WC()->cart->add_to_cart()逐个添加商品,并传递附加组件数据 - 可选重定向到购物车页面,避免重复提交
- 检测URL中的数组形式参数
移除原
woocommerce_add_cart_item_data钩子绑定:- 批量处理时已直接传递
cart_item_data,无需再通过该钩子处理
- 批量处理时已直接传递
内容的提问来源于stack exchange,提问作者Amesey
相关产品推荐
相关产品推荐

