Maximum Quantity Field per Product
Adds a "Maximum per order" field to the product Inventory tab and enforces it in the quantity box and the cart, for limited releases or allocated stock.
Opens WPIDE on
Code
add_action( 'woocommerce_product_options_inventory_product_data', function () {
global $product_object;
woocommerce_wp_text_input( array(
'id' => '_wpide_max_qty',
'label' => 'Maximum per order',
'type' => 'number',
'custom_attributes' => array( 'min' => 1, 'step' => 1 ),
'desc_tip' => true,
'description' => 'Leave empty for no limit.',
'value' => $product_object instanceof WC_Product ? $product_object->get_meta( '_wpide_max_qty' ) : '',
) );
} );
add_action( 'woocommerce_admin_process_product_object', function ( $product ) {
// phpcs:ignore WordPress.Security.NonceVerification -- WooCommerce verifies the product save nonce.
if ( isset( $_POST['_wpide_max_qty'] ) ) {
$max = absint( wp_unslash( $_POST['_wpide_max_qty'] ) );
$max ? $product->update_meta_data( '_wpide_max_qty', $max ) : $product->delete_meta_data( '_wpide_max_qty' );
}
} );
$wpide_max_for = function ( $product ) {
$id = $product->get_parent_id() ? $product->get_parent_id() : $product->get_id();
return absint( get_post_meta( $id, '_wpide_max_qty', true ) );
};
add_filter( 'woocommerce_quantity_input_args', function ( $args, $product ) use ( $wpide_max_for ) {
$max = $wpide_max_for( $product );
if ( $max ) {
$args['max_value'] = isset( $args['max_value'] ) && $args['max_value'] > 0 ? min( $args['max_value'], $max ) : $max;
}
return $args;
}, 10, 2 );
add_filter( 'woocommerce_available_variation', function ( $data, $product, $variation ) use ( $wpide_max_for ) {
$max = $wpide_max_for( $variation );
if ( $max ) {
$data['max_qty'] = '' === $data['max_qty'] ? $max : min( (int) $data['max_qty'], $max );
}
return $data;
}, 10, 3 );
add_action( 'woocommerce_check_cart_items', function () use ( $wpide_max_for ) {
$totals = array();
foreach ( WC()->cart->get_cart() as $item ) {
$totals[ $item['product_id'] ] = ( $totals[ $item['product_id'] ] ?? 0 ) + (int) $item['quantity'];
}
foreach ( $totals as $product_id => $qty ) {
$product = wc_get_product( $product_id );
$max = $product ? $wpide_max_for( $product ) : 0;
if ( $max && $qty > $max ) {
wc_add_notice( sprintf( 'You can buy up to %1$d of "%2$s" per order.', $max, esc_html( $product->get_name() ) ), 'error' );
}
}
} );
Notes
Leave the field empty for no limit; variations follow the limit set on their parent product.
How to add this snippet
- Install WPIDE on your WordPress site (it is free) and open Code Snippets.
- Use snippet above adds it from the library in one click. Or copy the code into a new snippet with the same code type.
- It is added inactive: review the code and settings, then switch it on.