Search code examples
phpwordpresswoocommercecarttaxonomy-terms

Limit purchases to items having the same product attribute in WooCommerce


I am using the code snippet below to limit the purchase of one unique WooCommerce product per order, because of logistic reasons (multiple warehouses). I use an attribute to specify the warehouse and it would be convenient to allow customers to order multiple products if the warehouse/attribute is the same. Could someone help me with changing the code snippet?

add_filter( 'woocommerce_add_to_cart_validation', 'wc_limit_one_per_order', 10, 2 );
function wc_limit_one_per_order( $passed_validation, $product_id ) {
    
    if ( WC()->cart->get_cart_contents_count() >= 1 ) {
        wc_add_notice( __( 'This product cannot be purchased with other products. Please, empty your cart first and then add it again.', 'woocommerce' ), 'error' );
        return false;
    }

    return $passed_validation;
}

I thought adding something like this, but I don't know how to proceed..

$attribute = $product->get_attribute('pa_warehouse');
foreach (WC()->cart->get_cart() as $cart_item_key => $values) {
$product = $values['data'];

Solution

  • Try the following revised code:

    add_filter( 'woocommerce_add_to_cart_validation', 'filter_add_to_cart_validation', 10, 4 );
    function filter_add_to_cart_validation( $passed, $product_id, $quantity, $variation_id = null ) {
        $product    = wc_get_product( $product_id );
        $warehouse  = $product->get_attribute('pa_warehouse');
        $cart_items = WC()->cart->get_cart();
    
        if ( WC()->cart->is_empty() ) {
            return $passed;
        }
        // Loop through cart items
        foreach ( WC()->cart->get_cart() as $values ) {
            // Check if the warehouse is different
            if ( $warehouse !== $values['data']->get_attribute('pa_warehouse') ) {
                wc_add_notice( __( 'This product cannot be purchased because...', 'woocommerce' ), 'error' );
                return false;
            }
        }
        return $passed;
    }
    

    Code goes in functions.php file of your child theme (or in a plugin). It should work.