WooCommerce禁止指定商品类别混加购物车问题求助
问题:WooCommerce商品类别互斥规则实现修复
需求说明
- 允许混加的类别:cheese、cheese-sets、bread、bakery、milk(这些类别商品可互相添加至购物车)
- 禁止混加的类别:glamp、horse、foodtruck、other、farm(这些类别既不能和允许类别混加,也不能互相混加)
- 触发规则时:跳转回商品页并显示错误提示
现有问题
参考代码修改后,仅能阻止允许类别与禁止类别混加,但禁止类别之间的商品仍可同时加入购物车,无法触发限制规则。
原参考代码
<?php //*** Prevent mixture of paint and other prods in same cart ***// function dont_add_paint_to_cart_containing_other($validation, $product_id) { // Set flag false until we find a product in cat paint $cart_has_paint = false; // Set $cat_check true if a cart item is in paint cat foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { $product = $cart_item['data']; if (has_term('paint', 'product_cat', $product->id)) { $cart_has_paint = true; // break because we only need one "true" to matter here break; } } $product_is_paint = false; if (has_term('paint', 'product_cat', $product_id)) { $product_is_paint = true; } // Return true if cart empty if (!WC()->cart->get_cart_contents_count() == 0) { // If cart contains paint and product to be added is not paint, display error message and return false. if ($cart_has_paint && !$product_is_paint) { wc_add_notice('Sorry, you can only purchase paint products on their own. To purchase this product, please checkout your current cart or empty your cart and try again', 'error'); $validation = false; } // If cart contains a product that is not paint and product to be added is paint, display error message and return false. elseif (!$cart_has_paint && $product_is_paint) { wc_add_notice('Sorry, you can only purchase paint products on their own. To purchase this product, please checkout your current cart or empty your cart and try again', 'error'); $validation = false; } } // Otherwise, return true. return $validation; } add_filter('woocommerce_add_to_cart_validation', 'dont_add_paint_to_cart_containing_other', 10, 2); ?>
修改后未完全生效的代码
<?php //*** Prevent mixture of certain categories in same cart ***// function dont_add_categories_to_cart_containing_other($validation, $product_id) { // Set flag false until we find a product in prohibited categories $cart_has_prohibited = false; // Prohibited categories $prohibited_categories = array( 'glamp', 'horse', 'foodtruck', 'other', 'farm' ); // Allowed categories $allowed_categories = array( 'cheese', 'cheese-sets', 'bread', 'bakery', 'milk' ); // Set $cat_check true if a cart item is in prohibited categories foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) { $product = $cart_item['data']; $product_categories = wp_get_post_terms($product->id, 'product_cat', array("fields" => "slugs")); $intersect_categories = array_intersect($prohibited_categories, $product_categories); if (!empty($intersect_categories)) { $cart_has_prohibited = true; // break because we only need one "true" to matter here break; } } $product_categories = wp_get_post_terms($product_id, 'product_cat', array("fields" => "slugs")); $intersect_categories = array_intersect($prohibited_categories, $product_categories); $product_is_prohibited = !empty($intersect_categories); // Return true if cart empty if (!WC()->cart->is_empty()) { // If cart contains prohibited categories and product to be added is not prohibited, display error message and return false. if ($cart_has_prohibited && !$product_is_prohibited) { wc_add_notice('Sorry, you can only purchase products from the allowed categories. Please checkout your current cart or empty your cart and try again.', 'error'); $validation = false; } // If cart contains a product that is not prohibited and product to be added is from the prohibited categories, display error message and return false. elseif (!$cart_has_prohibited && $product_is_prohibited) { wc_add_notice('Sorry, you can only purchase products from the allowed categories. Please checkout your current cart or empty your cart and try again.', 'error'); $validation = false; } } // Otherwise, return true. return $validation; } add_filter('woocommerce_add_to_cart_validation', 'dont_add_categories_to_cart_containing_other', 10, 2); ?>
修复后的代码及说明
问题核心在于原修改代码仅判断购物车是否存在禁止类别商品,未限制禁止类别之间的互加——只要同属禁止类别就允许添加,不符合需求。
修复思路:
- 区分购物车的三种状态:空、含允许类别商品、含禁止类别商品
- 针对禁止类别状态,新增判断:只要购物车已有某禁止类别商品,新添加的禁止类别商品无论属于哪个子类,都直接阻止
- 优化类别判断逻辑,适配WooCommerce最新属性调用规范
修复后的代码:
<?php //*** Prevent mixture of certain categories in same cart ***// function dont_add_categories_to_cart_containing_other($validation, $product_id) { // 定义类别组 $allowed_categories = array('cheese', 'cheese-sets', 'bread', 'bakery', 'milk'); $prohibited_categories = array('glamp', 'horse', 'foodtruck', 'other', 'farm'); // 获取当前要添加商品的类别归属 $current_product_cats = wp_get_post_terms($product_id, 'product_cat', array("fields" => "slugs")); $is_allowed = !empty(array_intersect($allowed_categories, $current_product_cats)); $is_prohibited = !empty(array_intersect($prohibited_categories, $current_product_cats)); // 购物车为空时直接通过验证 if (WC()->cart->is_empty()) { return $validation; } // 检查购物车中已有商品的类别状态 $cart_has_allowed = false; $cart_has_prohibited = false; foreach (WC()->cart->get_cart() as $cart_item) { $cart_product_cats = wp_get_post_terms($cart_item['data']->get_id(), 'product_cat', array("fields" => "slugs")); // 判断购物车是否包含允许类别商品 if (!empty(array_intersect($allowed_categories, $cart_product_cats))) { $cart_has_allowed = true; break; } // 判断购物车是否包含禁止类别商品 if (!empty(array_intersect($prohibited_categories, $cart_product_cats))) { $cart_has_prohibited = true; break; } } // 执行规则验证 if ($cart_has_allowed) { // 购物车有允许类别商品,仅能添加同组允许类别 if (!$is_allowed) { wc_add_notice('抱歉,当前购物车商品仅能与奶酪、面包、牛奶类商品混加,请先结算或清空购物车后再添加该商品。', 'error'); $validation = false; } } elseif ($cart_has_prohibited) { // 购物车有禁止类别商品,既不能加允许类别,也不能加其他禁止类别 if ($is_allowed || $is_prohibited) { wc_add_notice('抱歉,该类别商品无法与当前购物车商品混加,请先结算或清空购物车后再添加。', 'error'); $validation = false; } } return $validation; } add_filter('woocommerce_add_to_cart_validation', 'dont_add_categories_to_cart_containing_other', 10, 2); ?>
代码说明:
- 新增
$cart_has_allowed状态判断,确保允许类别组内仅能添加同组商品 - 针对禁止类别组,只要购物车已有任意禁止类别商品,新添加的任何禁止类别商品都会被阻止
- 使用
get_id()替代旧版的id属性,适配WooCommerce 3.0+版本的对象调用规范 - 优化错误提示文案,让用户更清晰理解限制规则
内容的提问来源于stack exchange,提问作者Bubble
相关产品推荐
相关产品推荐

