Categories
WooCommerce

Limit quantity of products per order for WooCommerce

There are times when you might want to put a limit on the quantity of a product a customer can have on an order. Maybe you have a product that has low stock and you want to make sure many people get to purchase it, or maybe it’s a product that really does not need to be bought in multiples (like a digital product maybe?).

In this code example, I’m going to work through the process of limiting product quantities for simple products only. I might do a variations example later 🙂

What do we need to account for?

First, let’s think through when we might need to check for a product limit. Here’s what I came up with that I think should cover most cases:

  1. When customers click “Add to Cart” on the product page
  2. When customers click “Add to Cart” from the Shop page
  3. In the cart itself, a customer could increase the quantity and update the cart
  4. We should also make sure Checkout is not possible if you exceed the maximum quantity we set

Our code example needs to account for all of these so that we have something that will work on a real store.

What hooks does WooCommerce provide?

There are two main hooks we want to use for this implementation.

Action: woocommerce_check_cart_items

Cart validation: https://github.com/woocommerce/woocommerce/blob/4.5.1/includes/shortcodes/class-wc-shortcode-cart.php#L91

Checkout validation: https://github.com/woocommerce/woocommerce/blob/4.5.1/includes/shortcodes/class-wc-shortcode-checkout.php#L272

The woocommerce_check_cart_items action runs when outputting the cart and it also runs when validating the checkout. This action lets us loop through the cart items and check if a specific product is over the quantity. If its quantity is higher than we set, we output an error and the checkout process is blocked.

Here’s an example for how you might use this:
(I add in a lot of code comments explaining what the code does!)

<?php // only add this line if it's at the top of a new PHP file

add_action( 'woocommerce_check_cart_items', 'set_max_for_cart_item' );

function set_max_for_cart_item() {
	// Set the product ID for the product you want to limit
	$check_product_id = 121;
	// Set the maximum quantity
	$maximum_quantity = 2;

	// Loop through the Cart items
	foreach ( WC()->cart->get_cart() as $key => $values ) {
		$_product = $values['data'];
		// Check for the speicifc product
		if ( $check_product_id === $values['product_id'] && $values['quantity'] > $maximum_quantity ) {	
			// If we match the product, we set an error message
			$message = sprintf( __( 'You can only have a maximum of %d for the product "%s".' ), $maximum_quantity, $_product->get_title() );

			wc_add_notice( $message, 'error' );
			return;
		}
	}
}

Ok, now to the next hook!

Filter: woocommerce_add_to_cart_validation

Source: https://github.com/woocommerce/woocommerce/blob/4.5.1/includes/class-wc-form-handler.php#L804

The woocommerce_add_to_cart_validation filter lets us filter the product, quantity, and whether or not it’s a valid action being performed. For example, if the total quantity is higher than our desired amount, we would set the valid argument as being false so that the action would not be allowed.

One interesting thing is that we also need to account for items currently in the cart, because the total is not just from what’s currently being added but what the total will be once we’ve added something to the cart.

Here’s an example of how this could be done:

<?php // only add this line if it's at the top of a new PHP file

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

function validate_add_to_cart_action( $valid, $product_id, $quantity ) {
	// Set the product ID for the product you want to limit
	$check_product_id = 121;
	// We want to check two quantities, the current cart and how many you are currently adding.  We're going to be adding them together into one variable called total_quantity.
	$total_quantity = $quantity;
	$maximum_quantity = 2;
	
	// Setting the default to valid
	$valid = true;

	// Checking if it's the product ID we want to target
	if ( $check_product_id === $product_id ) {
		// Loop through the items in the cart first
		foreach ( WC()->cart->get_cart() as $cart_item_key => $values ) {
			// If the item in the cart matches our product id, we'll add the current cart quantity to our total quantity
			if ( $values['product_id'] === $check_product_id ) {
				$total_quantity += $values['quantity'];
			}
		}
		// Let's check our total quantity now and see if it's above our maximum - if so, we'll display an error message
		if ( $total_quantity > 0 && $total_quantity > $maximum_quantity ) {
			// Grab the product object so we can output which product has the issue
			$_product = wc_get_product( $product_id );

			$message = sprintf( 'You can only have a maximum quantity of %d for the %s product (you currently have %d in your cart).', $maximum_quantity, $_product->get_title(), $total_quantity - $quantity );

			wc_add_notice( $message, 'error' );
	
			$valid = false;
		}
	}
	return $valid;
}

Tested on

WooCommerce 4.5.1 ✔
Storefront 2.7.0 ✔

Can I do this with a plugin?

My example here covers a very basic implementation where we’re only dealing with one simple product and one quantity. If that’s all you need, great! If you need more, there are some plugins that might help:

WooCommerce Min/Max Quantities ($29)

Disclaimer: I am not paid to recommend this and I make no money on suggesting this.

Aren’t they great at naming things? It does exactly that but also a lot more that I didn’t even think about. The plugin can set min/max quantites per:

  • Product
  • Variation
  • Category
  • Total of combined items at checkout
  • Cost (you can set a min/max cart cost)

And you can also:

  • Add exclusions from rules
  • Set groups/multiple rules (You need to buy product in groups of 3, etc)

Updated: Very often 🏅
Developer: (WooCommerce) Trusted 🏅

WooCommerce Max Quantity (Free)

This plugin does one thing – it lets you set a Maximum Quantity per product! It supports simple products, and it might support variable products but not individual variations. It appears to be updated about yearly and the code appears to be written well for what it does.

Updated: About yearly
Developer: Single Contributor

Final thoughts

If you need something simple, my code will work! If you need something that will be updated frequently and have customer support, go for the WooCommerce plugin.

You can see the full source of my example here:
https://gist.github.com/mikeyarce/f19d4b8601644212f734608d9bbf72a9

Leave a Reply