简体   繁体   English

限制 Woocommerce 购物车中免费产品的最大数量

[英]Limit maximum quantity of free products in Woocommerce cart

My client has asked for the ability to offer free samples of their variable products on their Woocommerce online store, with a maximum of 1 of each unique product sample and 5 of any of the samples on their order.我的客户要求能够在他们的 Woocommerce 在线商店上提供其可变产品的免费样品,每个独特的产品样品最多 1 个,订单上的任何样品最多 5 个。

I've achieved part of this by adding an extra “Free Sample” variation to each product and then using a free Min/Max quantity plugin to limit the amount of each individual free sample to 1 per order, please see the following screenshots:我通过为每个产品添加一个额外的“免费样品”变体,然后使用免费的最小/最大数量插件将每个单独的免费样品的数量限制为每个订单 1 个,从而实现了其中的一部分,请参阅以下屏幕截图:

https://ibb.co/f0Wd7XC https://ibb.co/8DrsZZj https://ibb.co/f0Wd7XC https://ibb.co/8DrsZZj

So far I haven't established a way to limit the maximum number of any combination of the “Free Sample” variations to 5 though.到目前为止,我还没有建立一种方法来将“免费样品”变体的任何组合的最大数量限制为 5。 The only way I can see is by limiting the total number of free products (ie price = £0) per order to 5, or alternatively by assigning a specific shipping class to each variation (ie”Free Samples”) and then somehow limiting the amount of products assigned with this shipping class in each order to 5. Is this possible?我能看到的唯一方法是将每个订单的免费产品总数(即价格 = 0 英镑)限制为 5 个,或者通过为每个变体分配特定的运输类别(即“免费样品”),然后以某种方式限制每个订单中分配有此运输类别的产品数量为 5。这可能吗?

Cheers,干杯,

M. M。

Woocommerce have validation hook which you can use. Woocommerce 具有您可以使用的验证钩子。

First one is when we add to our cart第一个是当我们添加到购物车时

function add_to_cart_free_samples($valid, $product_id, $quantity) {
    $max_allowed = 5;
    $current_cart_count = WC()->cart->get_cart_contents_count();
    foreach (WC()->cart->get_cart() as $cart_item_key=>$cart_item ){
        // Here change attribute group if needed - currently assigned to default size attribute
        $variation = $cart_item['variation']['attribute_pa_size'];
    }
    if( ( $current_cart_count > $max_allowed || $current_cart_count + $quantity > $max_allowed ) && $variation === 'free-sample' && $valid ){
        wc_add_notice( sprintf( __( 'Whoa hold up. You can only have %d items in your cart', 'your-textdomain' ), $max_allowed ), 'error' );
        $valid = false;
    }

    return $valid;
}

add_filter( 'woocommerce_add_to_cart_validation', 'add_to_cart_free_samples', 10, 3 );

Second one is when we update the cart on cart page for example.第二个是当我们更新购物车页面上的购物车时。

function update_add_to_cart_free_samples( $passed, $cart_item_key, $values, $updated_quantity ) {

    $cart_items_count = WC()->cart->get_cart_contents_count();
    $original_quantity = $values['quantity'];
    $max_allowed = 5;
    $total_count = $cart_items_count - $original_quantity + $updated_quantity;
    foreach (WC()->cart->get_cart() as $cart_item_key=>$cart_item ){
        // Here change attribute group if needed - currently assigned to default size attribute
        $variation = $cart_item['variation']['attribute_pa_size'];
    }
    if( $cart_items_count > $max_allowed && $variation === 'free-sample' ){
        $passed = false;
        wc_add_notice( sprintf( __( 'Whoa hold up. You can only have %d items in your cart', 'your-textdomain' ), $max_allowed ), 'error' );
    }
    return $passed;
}
add_filter( 'woocommerce_update_cart_validation', 'update_add_to_cart_free_samples', 10, 4 );

In $cart_item you can debug and see all info for the current product in the cart.在 $cart_item 中,您可以调试并查看购物车中当前产品的所有信息。 From there you can add condition depending on shipping or attribue or price or w/e you want.从那里您可以根据运输或属性或价格或您想要的 w/e 添加条件。

This is what you are looking for (NO PLUGIN NEEDED):这就是您正在寻找的(无需插件):

In the theme's function.php add the following:在主题的 function.php 中添加以下内容:

/*----------------------------------------------------------
 * Adds custom field to the inventory tab in the product data meta box
 * ---------------------------------------------------------- */
function action_woocommerce_product_options_stock_status() {        
    woocommerce_wp_text_input(
        array(
            'id'                => '_max_qty',
            'placeholder'       => __( 'Set the bundle maximum to at least 2 items or leave blank', 'woocommerce' ),
            'label'             => __( 'Maximum Bundle', 'woocommerce' ),
            'desc_tip'          => true,
            'description'       => __( 'Limits the maximum amount of product bundles your customer can order', 'woocommerce' ),
            'type'              => 'number',
            'custom_attributes' => array(
                'step' => 'any',
            ),
        )
    );
}
add_action( 'woocommerce_product_options_stock_status', 'action_woocommerce_product_options_stock_status', 10, 0 );

/* ----------------------------------------------------------
 * Save custom field to the inventory tab in the product data meta box
 * ---------------------------------------------------------- */
function action_woocommerce_admin_process_product_object( $product ) {
    // Isset
    if ( isset( $_POST['_max_qty'] ) ) {        
        // Update
        $product->update_meta_data( '_max_qty', sanitize_text_field( $_POST['_max_qty'] ) );
    }
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );

function get_cart_quantity_variable_product( $child_ids ) { 
    // Get cart items quantities
    $cart_item_quantities = WC()->cart->get_cart_item_quantities();
    
    // Counter
    $qty = 0;
    
    // Loop through the childIDs
    foreach ( $child_ids as $child_id ) {
        // Checks if the given key or index exists in the array
        if ( array_key_exists( $child_id, $cart_item_quantities ) ) {
            // Addition
            $qty += $cart_item_quantities[$child_id];
        }
    }
    
    return $qty;
}

function action_woocommerce_check_cart_items() {    
    // Will increment
    $i = 0;
    
    // Will hold information about products that have not met the minimum order quantity
    $bad_products = array();
    
    // Will hold information about which product ID has already been checked so that this does not happen twice (especially applies to products with variants)
    $already_checked = array();
    
    // Loop through cart items
    foreach( WC()->cart->get_cart() as $cart_item ) {
        // Get IDs
        $product_id = $cart_item['product_id'];
        $variation_id = $cart_item['variation_id'];
        
        // NOT in array, already checked? Continue
        if ( ! in_array( $product_id, $already_checked ) ) {            
            // Push to array
            $already_checked[] = $product_id;
            
            // Get the parent variable product for product variation items
            $product = $variation_id > 0 ? wc_get_product( $product_id ) : $cart_item['data'];
            
            // Get meta
            $max_qty = $product->get_meta( '_max_qty', true );
            
            // NOT empty & minimum quantity is lesser than or equal to 5 (1 never needs to be checked)
            if ( ! empty( $max_qty ) && $max_qty <= 5 ) {               
                // Get current quantity in cart
                $cart_qty = $cart_item['quantity'];
                
                // Product type = variable & cart quantity is less than the maximum quantity
                if ( $product->get_type() == 'variable' && ( $cart_qty < $max_qty ) ) {                 
                    // Get childIDs in an array
                    $child_ids = $product->get_children();

                    // Call function, get total quantity in cart for a variable product
                    $cart_qty = get_cart_quantity_variable_product( $child_ids );               
                }
                
                // Cart quantity is less than the maximum quantity
                if ( $cart_qty > $max_qty ) {
                    // The product ID
                    $bad_products[$i]['product_id'] = $product_id;
                    
                    // The variation ID (optional)
                    //$bad_products[$i]['variation_id'] = $variation_id;                    
                    
                    // The Product quantity already in the cart for this product
                    $bad_products[$i]['in_cart'] = $cart_qty;
                    
                    // Get the maximum required for this product
                    $bad_products[$i]['max_req'] = $max_qty;
                    
                    // Increment $i
                    $i++;
                }
            }
        }
    }
    
    // Time to build our error message to inform the customer, about the maximum quantity per order.
    if ( is_array( $bad_products) && count( $bad_products ) < 5 ) { 
        // Clear all other notices          
        wc_clear_notices();
        
        foreach( $bad_products as $bad_product ) {
            // Displaying an error notice
            wc_add_notice( sprintf(
                __( '%s has a maximum quantity of %d. You currently have %d in cart', 'woocommerce' ),
                get_the_title( $bad_product['product_id'] ),
                $bad_product['max_req'],
                $bad_product['in_cart'],
            ), 'error' );
        }
        
        // Optional: remove proceed to checkout button
        remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
    }
}   
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );

Credit goes to 7uc1f3r for the solution on: Force minimum order quantity for specific products including variations on WooCommerce cart page归功于 7uc1f3r 的解决方案: 强制特定产品的最低订购数量,包括 WooCommerce 购物车页面上的变体

I only added and changed some code to fit it for the maximum bundle.我只添加并更改了一些代码以使其适合最大捆绑包。 This works for free samples stuff and you can also use it for any product the shop owner wants to limit to a set amount of bundle, as this isn't hardcoding the limit to a certain product.这适用于免费样品,您也可以将它用于店主希望限制为一定数量的捆绑包的任何产品,因为这不是对特定产品的限制进行硬编码。

Here is an example of this working:这是此工作的示例:

功能示例

功能示例 2

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM