Allow Only One Specific Product in the WooCommerce Cart at a Time

In some WooCommerce setups you may need to enforce a rule where a customer can hold only one specific product in the cart at a time — for example, a subscription token or an event ticket. Clicking “Add to cart” a second time should remove the existing item rather than increasing the quantity.

Problem: The business rule requires that customers can only purchase one instance of a specific WooCommerce product at a time — adding it again should be blocked or replace the existing cart item.

Solution: Hook into woocommerce_add_to_cart_validation, check whether the target product ID is already in the cart using WC()->cart->get_cart(), and return false with wc_add_notice() to block a duplicate. Alternatively, call WC()->cart->empty_cart() first to replace the existing item.

There are two approaches, both relying on WooCommerce's cart API.

Approach 1 — iterate over the cart:

<?php
$product_id = 555;

foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
    if ( (int) $cart_item['product_id'] === $product_id ) {
        WC()->cart->remove_cart_item( $cart_item_key );
        return; // item removed; do not add it again
    }
}

WC()->cart->add_to_cart( $product_id, 1 );

Approach 2 — use the cart hash. WooCommerce generates a deterministic hash for each unique cart item based on the product ID and variation data. You can generate the hash yourself and check whether it already exists:

<?php
$product_id        = 555;
$cart_item_hash    = WC()->cart->generate_cart_id( $product_id );
$existing_item_key = WC()->cart->find_product_in_cart( $cart_item_hash );

if ( $existing_item_key ) {
    WC()->cart->remove_cart_item( $existing_item_key );
} else {
    WC()->cart->add_to_cart( $product_id, 1 );
}

Approach 2 is cleaner and more reliable — it avoids iterating over the entire cart and works correctly with product variations, since the hash incorporates variation data.

Both snippets are typically placed inside a custom AJAX handler or a WooCommerce action hook such as woocommerce_add_to_cart.

NOTE: generate_cart_id() accepts additional arguments for variation ID, variation attributes, and cart item data — pass the same arguments that add_to_cart() will receive to ensure the hash matches correctly for variable products.