问题
I want to do something simple: do not ship a particular product to Canada.
Here's the easiest way to do it in my opinion: if that particular product is present in the cart, remove Canada from checkout page.
Particular products:
1- https://constructioncovers.com/product/insulated-cement-curing-blankets/ (ID: 12616)
2- https://constructioncovers.com/product/insulated-construction-tarps/ (ID: 15631)
My research:
This article gave me a way to find products in cart and perform any action if condition is true: https://businessbloomer.com/woocommerce-easily-check-product-id-cart/ This article gave me a way to remove specific country from checkout page How to remove specific country in WooCommerce I have combined and modified the two codes to try and accomplish my task. Here's my code:
function unset_country_on_condition( $country ) {
$product_id = 15631;
$product_id_2 = 12616;
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$product_cart_id_2 = WC()->cart->generate_cart_id( $product_id_2 );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
$in_cart_2 = WC()->cart->find_product_in_cart( $product_cart_id_2 );
if ( $in_cart || $in_cart_2 ) {
unset($country["CA"]);
return $country;
}
}
add_filter( 'woocommerce_countries', 'unset_country_on_condition', 10, 1 );
But the above function doesn't work
. It makes the country dropdown empty resulting in a site-wide warning notice.
Can someone point out what I am doing wrong?
Screenshots:
回答1:
The following code will remove "Canada" from allowed countries when specific products are in cart:
add_filter( 'woocommerce_countries', 'products_disable_country', 10, 1 );
function products_disable_country( $countries ) {
if( is_cart() || is_checkout() ) {
$products = array(15631, 12616);
foreach( WC()->cart->get_cart() as $item ){
if( in_array( $item['product_id'], $products ) ){
unset($countries["CA"]);
return $countries;
}
}
}
return $countries;
}
Code goes in function.php file of your active child theme (active theme). tested and work.
回答2:
Edited from this answer
add_filter( 'woocommerce_countries', 'unset_country_on_condition', 10, 1 );
function unset_country_on_condition( $countries ) {
// Set here your to add product IDS (in the array)
$product_ids = array( 15631, 12616 );
$is_in_cart = false;
// Iterating through cart items and check
foreach( WC()->cart->get_cart() as $cart_item_key => $cart_item )
if( in_array( $cart_item['data']->get_id(), $product_ids ) ){
$is_in_cart = true; // We set it to "true"
break; // At least one product, we stop the loop
}
if( $is_in_cart ){
unset($countries["CA"]);
}
return $countries;
}
回答3:
Unfortunately, as of WooCommerce 3.6.2
, they have removed the ability to check the cart in any backend calls, according to the ticket I opened. I was running a similar filter on woocommerce_countries
, to restrict certain items in the cart to only be purchasable at certain locations, and got a fatal error after I updated a few days ago.
WC have said they won't fix the issue, as it's intended behaviour to speed things up. However, you can still access the cart in this filter by doing the following:
function vnm_disable_country_for_products($countries) {
// get_cart() will fail here in WC > 3.6.2, but we can still access a basic cart via the session:
$cartArray = WC()->session->cart;
if (is_array($cartArray) && !empty($cartArray)) {
$noSaleCountry = 'CA';
$limitingProducts = array(12616, 15631);
foreach ($cartArray as $itemArray) {
if (in_array($itemArray['product_id'], $limitingProducts)) {
unset($countries[$noSaleCountry]);
}
}
return $countries;
}
add_filter('woocommerce_countries', 'vnm_disable_country_for_products', 10, 1);
This is ostensibly the same as Loic's answer; however as WC()->cart->get_cart()
is no longer available, we're accessing the cart via WC()->session->cart
instead.
回答4:
Can you try following code.
global $product_check; //declare a global variable
function remove_canada_insulated_blankets_traps(){
$product_ids = array(12616,15631);
foreach($product_ids as $product_id){
$product_cart_id = WC()->cart->generate_cart_id( $product_id );
$in_cart = WC()->cart->find_product_in_cart( $product_cart_id );
$product_check[$in_cart]; //global variable is converted into an array storing ids
}
}
add_action( 'woocommerce_before_cart', 'remove_canada_insulated_blankets_traps' );
//pass the global variable into following function as another argument
function woo_remove_canada_country( $countries, $product_check ){
if( count(product_check) > 0 ){ //check count of the array
unset($countries['CA']); //unset country
}
return $countries;
}
add_filter( 'woocommerce_countries', 'woo_remove_canada_country', 10, 2 );
Notice the change in last argument of 'woocommerce_countries' filter. Since additional argument is passed to the function the last argument is changed to 2 instead of 1.
来源:https://stackoverflow.com/questions/53321692/remove-canada-from-country-list-when-specific-products-are-in-cart-on-woocommerc