Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
661 views
in Technique[技术] by (71.8m points)

php - Restricting cart items to be from the same product category in WooCommerce

I am using the code below to remove other WooCommerce product category items from the cart when there is an item with a special product category 'cat_x' added in cart and display some different custom notices. The code came from this thread and just works well:

add_action( 'woocommerce_check_cart_items', 'checking_cart_items' );
function checking_cart_items() {
    $special = false;
    $catx = 'cat_x';
    $number_of_items = sizeof( WC()->cart->get_cart() );

    if ( $number_of_items > 0 ) {

        // Loop through all cart products
        foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
            $item = $values['data'];
            $item_id = $item->id;

            // detecting if 'cat_x' item is in cart
            if ( has_term( $catx, 'product_cat', $item_id ) ) {
                if (!$special)
                    $special = true;
            }
        }

        // Re-loop through all cart products
        foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
            $item = $values['data'];
            $item_id = $item->id;

            if ( $special ) // there is a 'cat_x' item in cart
            { 
                if ( $number_of_items == 1 ) { // only one 'cat_x' item in cart
                    if ( empty( $notice ) )
                        $notice = '1';
                }
                if ( $number_of_items >= 2 ) { // 'cat_x' item + other categories items in cart
            // removing other categories items from cart
                    if ( !has_term( $catx, 'product_cat', $item_id ) ) {
                        WC()->cart->remove_cart_item( $cart_item_key ); // removing item from cart
                        if ( empty( $notice ) || $notice == '1' )
                            $notice = '2';
                    }
                }
            } else { // Only other categories items
                if ( empty( $notice ) )
                    $notice = '3';
            }
        }

        // Firing notices
        if ( $notice == '1' ) { // message for an 'cat_x' item only (alone)
            wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla one category X item in the cart</p>' ), 'success' );
        } elseif ( $notice == '2' ) { // message for an 'cat_x' item and other ones => removed other ones 
            wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla ther is already category X in the cart => Other category items has been removed</p>' ), 'error' );
        } elseif ( $notice == '3' ) { // message for other categories items (if needed)
            wc_add_notice( sprintf( '<p class="woocommerce-error">bla bla bla NOT category X in the cart</p>' ), 'success' );
        }
    }
} 

Has the conditional function has_term() works also with arrays of categories, I have tried instead of one category, to set an array of categories in that code. But it’s not working.

However, my needs have changed: I don’t want to let the customer have the possibility to select cart items from different categories. So the cart must always have items from the same product category.

Any help please?

Thanks.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Making a custom function hooked in woocommerce_add_to_cart_validation filter hook is going to do the job in a much more simpler way, without any need to set an array of categories.

So your code will be much more faster and compact. Additionally you can display a custom notice to warn the customer.

This code will avoid adding to cart, if an item of a different category is in cart:

add_filter( 'woocommerce_add_to_cart_validation', 'add_to_cart_validation_callback', 10, 3 );
function add_to_cart_validation_callback( $passed, $product_id, $quantity) {
    // HERE set your alert text message
    $message = __( 'MY ALERT MESSAGE.', 'woocommerce' );

    if( ! WC()->cart->is_empty() ) {
        // Get the product category terms for the current product
        $terms_slugs = wp_get_post_terms( $product_id, 'product_cat' array('fields' => 'slugs'));

        // Loop through cart items
        foreach (WC()->cart->get_cart() as $cart_item ){
            if( ! has_term( $terms_slugs, 'product_cat', $cart_item['product_id'] )) {
                $passed = false;
                wc_add_notice( $message, 'error' );
                break;
            }
        }
    }
    return $passed;
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

This code is tested and it works


Restricting cart items to be only from different product categories:

Replace in the function the condition:

if( ! has_term( $product_cats, 'product_cat', $cart_item['product_id'] )) { 

by

if( has_term( $product_cats, 'product_cat', $cart_item['product_id'] )) {

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...