WooCommerce移除购物车商品问题:已购商品无法加入购物车
Hey there, let's break down why your woocommerce_add_to_cart hook wasn't working and fix this properly.
Why Your Original Code Failed
The core issues are tied to hook execution timing and logic gaps:
- Timing mismatch: The
woocommerce_add_to_carthook fires immediately after a product is added to the cart, but WooCommerce hasn't fully persisted the cart changes to the session yet. When you loop throughWC()->cart->get_cart()at this point, the newly added item might not be included in the result, or your session-based token/data might not be fully loaded. - Incorrect comparison logic: Your original code only checks if the product SKU matches a single
$list->intvalue. If$listis a collection of all purchased SKUs (which it should be), this will only ever match one item instead of checking against all purchased products. - Inefficient cart traversal: Looping through the entire cart every time an item is added is unnecessary—you only need to check the item that was just added.
Fix 1: Prevent Adding Purchased Products (Better UX)
Instead of adding the item and then removing it, use the woocommerce_add_to_cart_validation hook to block the addition entirely. This gives users clearer feedback without the confusing "add-then-remove" behavior:
add_action('woocommerce_add_to_cart_validation', 'block_purchased_products', 10, 3); function block_purchased_products($passed, $product_id, $quantity) { // Use WooCommerce's session handler instead of raw $_SESSION for better compatibility $token = WC()->session->get('******token'); if (!$token) return $passed; $dataservice = *******Service::getService('DataService'); $purchased_skus = $dataservice->getArticleBlacklist($token); if (empty($purchased_skus)) return $passed; // Get the correct SKU (handles variations too) $product = wc_get_product($product_id); $sku_int = intval($product->get_sku()); // Check if the SKU exists in purchased items foreach ($purchased_skus as $purchased_item) { if ($sku_int === $purchased_item->int) { wc_add_notice(__('You’ve already purchased this product and can’t add it again.', 'woocommerce'), 'error'); return false; // Block the product from being added } } return $passed; }
Fix 2: Remove Purchased Items After Addition (If You Prefer This Flow)
If you still need to remove items post-addition, use the woocommerce_add_to_cart hook with parameters that let you target the exact item just added (no full cart loop needed):
add_action('woocommerce_add_to_cart', 'remove_purchased_product_post_add', 10, 6); function remove_purchased_product_post_add($cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data) { $token = WC()->session->get('******token'); if (!$token) return; $dataservice = *******Service::getService('DataService'); $purchased_skus = $dataservice->getArticleBlacklist($token); if (empty($purchased_skus)) return; // Get the SKU of the newly added item $target_product = $variation_id ? wc_get_product($variation_id) : wc_get_product($product_id); $sku_int = intval($target_product->get_sku()); // Check and remove if it's a purchased item foreach ($purchased_skus as $purchased_item) { if ($sku_int === $purchased_item->int) { WC()->cart->remove_cart_item($cart_item_key); wc_add_notice(__('This product was already purchased and has been removed from your cart.', 'woocommerce'), 'error'); break; } } }
Key Improvements in These Fixes
- Uses
WC()->sessioninstead of raw$_SESSIONto align with WooCommerce's session management (avoids issues with uninitialized sessions). - Targets only the relevant product instead of looping through the entire cart (faster and less error-prone).
- Properly handles product variations to get the correct SKU.
- Provides clear user feedback via WooCommerce notices.
内容的提问来源于stack exchange,提问作者Alex Schwifty
相关产品推荐
相关产品推荐

