skip to Main Content

If a woocommerce cart has a virtual item only it does not show shipping methods.

I have a unique situation where I’d like this to be the case also if the cart contains physical products but at least one virtual product (ie any virtual product in the cart, regardless of whatever else is in the cart, hide shipping methods). Whereas if no virtual products are in the cart then show shipping methods as normal.

I’ve tried the code below but it doesn’t seem to work:

Thanks for your help

 add_filter( 'woocommerce_cart_needs_shipping_address', 'filter_cart_needs_shipping_address_callback' );
function filter_cart_needs_shipping_address_callback( $needs_shipping_address ){
    // Loop through cart items
    foreach ( WC()->cart->get_cart() as $item ) {
        if ( $item['data']->is_virtual() ) {
            $needs_shipping_address = false;
            break; // Stop the loop
        }
    }
    return $needs_shipping_address;
}

2

Answers


  1. Chosen as BEST ANSWER

    Thanks, it was throwing the error "Uncaught Error: Call to a member function get_cart() on null" but have managed to fix it with this:

    if ( is_null( WC()->cart ) ) {
                    wc_load_cart();        
            } else 

    Let me know if there is a better way to do it? Thanks

    add_filter( 'woocommerce_cart_needs_shipping', 'filter_cart_needs_shipping_address_callback' );
    function filter_cart_needs_shipping_address_callback( $needs_shipping ){
        // Loop through cart items
        if ( is_null( WC()->cart ) ) {
                    wc_load_cart();        
            } else {
        foreach ( WC()->cart->get_cart() as $item ) {
            if ( $item['data']->is_virtual() ) {
                $needs_shipping = false;
                break; // Stop the loop
            }
        }
        return $needs_shipping;
    }
    }


  2. I think I figured out how to do it for you.
    The Hook you’re using in your example is not the right one since it’s just filtering the shipping address callback.

    What I think you need to do is use the woocommerce cart needs shipping hook.

    Since it was throwing an error you could try to only run the code on the cart and checkout page. You can do that by using if ( is_cart() || is_checkout() ) {

    Try the edited code below and let me know how it works.

    Have a wonderful day!

    add_filter( 'woocommerce_cart_needs_shipping', 'remove_virtual_product_shipping_methods' );
    function remove_virtual_product_shipping_methods( $needs_shipping ){
        //Only execute code on cart and checkout page.
         if ( is_cart() || is_checkout() ) {
            //Loop trough cart items
            foreach ( WC()->cart->get_cart() as $item ) {
                //If a product in cart is a vritual product remove all shipping
                if ( $item['data']->is_virtual() ) {
                    $needs_shipping = false;
                    break;
                }
            }
            return $needs_shipping;
        }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search