# 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.

- Type: PHP
- Runs: Run everywhere
- Category: [WooCommerce](https://wpide.com/library/category/woocommerce/)
- Requires: WooCommerce
- Tags: woocommerce, quantity, inventory, limits
- Author: WPIDE Team
- Installs: 0
- Updated: 2026-10-28
- Page: https://wpide.com/library/woo-product-max-quantity-field/

## Code

```php
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 use it

Install the free WPIDE plugin (https://wordpress.org/plugins/wpide/), find "Maximum Quantity Field per Product" in its snippet library and add it in one click; or create a new PHP snippet in WPIDE (or any code snippets plugin) and paste the code above. More snippets: https://wpide.com/library/
