Check if a Product Has Variations

In this simple tutorial I’d like to show you easy ways to check whether a specific product has variations or not.

The first thing you need to understand here is that variations are also a custom post type product_variation and “variation posts” are always child in relation to “product posts”.

The second thing is that we have public (“Enabled” checkbox is checked) and private (“Enabled” checkbox is unchecked) variations:

Enabled (public) and private variations of WooCommerce products

The thing is that depending on whether your variation is public or private, you need to use different functions and class methods.

Check Enabled Variations

If checking only enabled variations is ok for you, continue to read further, otherwise you can jump down to the second chapter of this tutorial. Because in this part we’re going to use get_available_variations() method and it works only with variations with the “Enabled” checkbox checked:

Example of a public (enabled) variation.

For example, let’s say you have a specific product ID and you need to check if this product has variations, right? You can easily do it like this:

$product_id = 12345;
$product = wc_get_product( $product_id );

if( $product->is_type( 'variable' ) ) {
	// it is a variable product, let's check if it has variations
	if( $product->get_available_variations() ) {
		// yes, it has
	} else {
		// nope, it has not
	}
} else {
	// not a variable product	
}

The question is – can we remove is_type( 'variable' ) condition here? Technically yes, but you need to be careful, because if you run get_available_variations() method for a simple product for example, you will get a fatal error “Uncaught Error: Call to undefined method WC_Product_Simple::get_available_variations()”. I know I know, we can always use something like method_exists( $product, 'get_available_variations' ) or maybe even is_a( $product, 'WC_Product_Variable' ) to double check it, but do we really need to do it if we can just easily check our product type.

What is also interesting about get_available_variations() is that it returns an array of variation arrays, so you can also get all the variation data without doing anything extra.

For example we can print variation prices like this:

$variations = $product->get_available_variations();
if( $variations ) {
	foreach( $variations as $variation ) {
		echo 'ID #' . $variation[ 'variation_id' ] . ', price: ' . $variation[ 'price_html' ];
   }
}

It is funny to see though in other examples over the internet, when authors are trying to use something like $variation->get_id() which will get you a fatal error like “Call to a member function get_id() on array…”.

Check Both Enabled and Private Variations

The private variations are those with the “Enabled” checkbox unchecked. I call them private because if you check this variation post status in the database, it is going to be private.

Example of a private WooCommerce product variation

Ok, but what if our variable product has only private “not enabled” variations, and we need to check them or even to get them. For example my Simple WP Crossposting plugin allows to crosspost both private and public variations, how I dealt with that?

Super-easy!

There is another great method get_children() which allows to get literally all the product variations (and doesn’t matter if all the variations are private). That means you can also use this method to check whther a specific WooCommerce product has variations or not, because if it doesn’t, this method will return an empty array.

$product_id = 12345;
$product = wc_get_product( $product_id );

if( $product->get_children() ) { // checking if a product has variations
	// it has variations
} else {
	// it doesn't have variations
}

As an option you can even use another method – has_child().

if( $product->has_child() ) {
	// it has variations
} else {
	// it doesn't have variations
}

As you can see I didn’t check a product type here, it is because both get_children() and has_child() methods can be called for any product type. For example you can use them when you need to get all the connected products in a grouped product as well.

And now, as an example, let’s try to get some variation data, why not:

$variations = $product->get_children();
if( $variations ) {
	foreach( $variations as $variation_id ) {
		$variation = wc_get_product_object( 'variation', $variation_id );
		// now we have WC_Product_Variation object
		echo 'ID #' . $variation->get_id() . ', price: ' . $variation->get_price_html();
   }
}

I know that came a little bit beyond the topic of this tutorial, just tried to overdeliver for you 🙃

Misha Rudrastyh

Misha Rudrastyh

Hey guys and welcome to my website. For more than 10 years I've been doing my best to share with you some superb WordPress guides and tips for free.

Need some developer help? Contact me

Follow me on X