Objective: add product to cart despite unselected variations, i.e. remove/disable the mandatory nature of variation fields.
Issue: WooCommerce's absolute requirement for all variations to be selected before adding to cart.
Tried: filtering out/removing/disabling unselected variations before adding to cart using various hooks; woocommerce_before_calculate_totals
, woocommerce_add_to_cart
, woocommerce_add_cart_item
, woocommerce_add_to_cart_validation
I understand that this is how WooCommerce works and the reasons why it works this way - despite this I still require a work-around.
How do I get around WooCommerce's "all variations selected" requirement so that I may still add a product to the cart even if not all variations are selected?
Go to WooCommerce > Settings > Better Variations. Check the checkbox next to the option 'Enable Select2'. Input '#ff0000' in the color picker field 'Out of stock text color' for displaying out-of-stock variation options in red color. Scroll down to the bottom and click the 'Save changes' button.
To set default attributes manually, first, in the WooCommerce dashboard go to Products and then click on your variable product. Then, select Variable product from the Product data dropdown. After that, under Variations, you have to select the Default Form Values.
This way can be used with both the same product ID and the different ones Another way to add multiple variations to carts in WooCommerce stores is via a third-party platform. This post will guide you on how to use the plugin WooCommerce Product Table to add more than one product to the cart on one page.
If you’re using a WooCommerce theme, it might come with dedicated theme features for your product pages. This might include hiding your Add to Cart button.
To better illustrate how to empty the cart programatically, let’s add a button to the cart which would allow customers to click on it and clear their cart. Let’s use the woocommerce_proceed_to_checkout action an echo our very own ‘Submit’ button which will clear the cart for the current customer.
Go to Product and click on Edit to edit the product you want. There, you will see the product ID. There are two ways to add multiple variations to the cart: Copy and paste it after ?add-to-cart=. Then, add &quantity=3 if you want to add two same products to the cart at the same time.
You can try
add_filter('woocommerce_dropdown_variation_attribute_options_args', 'setSelectDefaultVariableOption', 10, 1);
function setSelectDefaultVariableOption($args)
{
$default = $args['product']->get_default_attributes();
if (count($args['options']) > 0 && empty($default)) {
$args['selected'] = $args['options'][0];
}
return $args;
}
1 - You could use "variation" attributes, and "not-variation" attributes. UPDATED AFTER TESTS
For the attribute that will handle your product price:
create a variable product
create real Woocommerce product attributes (real taxonomy and terms) (it won't work with "created on product page" attributes, as it'll not create real taxonomy and terms)
Here I created 3 attributes with some terms
On your variable product, I choose all of my 3 attributes. But specified to only use Color and Size for variations (so Color and Variations will handle my prices variations), not the attribute "optional" (that will be an optional option)
Then, generate your variations. You can see here that I only have variations for a combination of Color and Size, nothing about the "Optional" attribute yet
Also, select the "default values" for your variation attributes. So on the frontend, the attribute select HTML input will have a pre-selected option (user can add to cart directly)
Now we have our variation attributes, with preselected values on the frontend
But we still miss our "optional" attributes
Add the following code to your function.php
or related (Inspired, updated/refreshed, and adapted from this) (sorry for formatting, snippet also available as gist)
This will handle outputting the select input for the optional attribute, saving it to cart and to order. You can adapt it to make it required or not, with a default value or not, edit HTML and placement with different hooks.
/**
* List available attributes on the product page in a drop-down selection
*/
function list_attributes_on_product_page() {
global $product;
$attributes = $product->get_attributes();
if ( ! $attributes ) {
return;
}
//from original script, but here we want to use it for variable products
/*if ($product->is_type( 'variable' )) {
return;
}*/
echo '<div style="padding-bottom:15px;">';
foreach ( $attributes as $attribute ) {
//If product is variable, and attribute is used for variation: woocommerce already handle this input - so it can also be used with attributes of simple products (not variables)
if($product->is_type( 'variable' ) && $attribute['variation']) {
continue;
}
//get taxonomy for the attribute - eg: Size
$taxonomy = get_taxonomy($attribute['name']);
//get terms - eg: small
$options = wc_get_product_terms( $product->get_id(), $attribute['name'], array( 'fields' => 'all' ) );
$label = str_replace('Product ', '', $taxonomy->label);
//display select input
?>
<div style="padding-bottom:8px;">
<label for="attribute[<?php echo $attribute['id']; ?>]"><?php echo $label; ?></label>
<br />
<!-- add required attribute or not, handle default with "selected" attribute depending your needs -->
<select name="attribute[<?php echo $attribute['id']; ?>]" id="attribute[<?php echo $attribute['id']; ?>]">
<option value disabled selected>Choose an option</option>
<?php foreach ( $options as $pa ): ?>
<option value="<?php echo $pa->name; ?>"><?php echo $pa->name; ?></option>
<?php endforeach; ?>
</select>
</div>
<?php
}
echo '</div>';
}
add_action('woocommerce_before_add_to_cart_button', 'list_attributes_on_product_page');
/**
* Add selected attributes to cart items
*/
add_filter('woocommerce_add_cart_item_data', 'add_attributes_to_cart_item', 10, 3 );
function add_attributes_to_cart_item( $cart_item_data, $product_id, $variation_id ) {
$attributes = $_POST['attribute'] ?? null;
if (empty( $attributes ) ) {
return $cart_item_data;
}
$cart_item_data['attributes'] = serialize($attributes);
return $cart_item_data;
}
/**
* Display attributes in cart
*/
add_filter( 'woocommerce_get_item_data', 'display_attributes_in_cart', 10, 2 );
function display_attributes_in_cart( $item_data, $cart_item ) {
if ( empty( $cart_item['attributes'] ) ) {
return $item_data;
}
foreach (unserialize($cart_item['attributes']) as $attributeID => $value) {
$attribute = wc_get_attribute($attributeID);
$item_data[] = array(
'key' => $attribute->name,
'value' => $value,
'display' => '',
);
}
return $item_data;
}
/**
* Add attribute data to order items
*/
add_action( 'woocommerce_checkout_create_order_line_item', 'add_attributes_to_order_items', 10, 4 );
function add_attributes_to_order_items( $item, $cart_item_key, $values, $order ) {
if ( empty( $values['attributes'] ) ) {
return;
}
foreach (unserialize($values['attributes']) as $attributeID => $value) {
$attribute = wc_get_attribute($attributeID);
$item->add_meta_data( $attribute->name, $value );
}
}
Results:
2 - Plugins
You could also check with plugins like Product Add-Ons or Extra Product Options (Product Addons) for WooCommerce. In addition to real Woocommerce product variations with your attribute handling prices, those plugins could allow you to add optional fields on the product level when adding it to the cart. It can be enough if you don't need real product variations for those "optional" attributes, but only "optional fields that will be saved to the order line-item product".
3 - with hooks (tweaks)
Now, if you really need to use hooks to handle this issue, and you already have variations for required and optional attributes. So you generated all product variations for all attributes. But in the end, only 1 attribute has a price impact, so many variations have the same price).
You could first try to handle it with "default" attributes values. So by only changing the "required price impacting" attribute, the user always has an existing product variation from the combination of attributes. So it can be added to the cart.
If for some reason, you cannot preselect the default yourself: still create the default attribute term, and hook before add to cart. There, from the POST variables, you could:
The thing is with the variable products: attributes are nothing for the checkout process. When user select options (attributes) on the frontend, he selects a combination of attribute that have or not a corresponding product variation (created by admin, or with woocommerce helper). Woocommerce needs an existing product variation (combination of attributes), that you can see on the product page, to add something to the cart. Those variations are in DB a custom post_type "product_variation" that can be added to the cart and to a order as line-item. If the combination of attributes doesn't have a matching product variation: there's nothing to add to the cart.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With