phpwordpresswoocommercetaxonomy-termsproduct-variations

How to Use Attributes Default Display Order for get_available_variations() Loop on Product Page?


I'm using a $product->get_available_variations() loop to display an image gallery of variations on the product page:

$variations = $product->get_available_variations();
foreach ( $variations as $variation ) { ?>
    <li>
        <img... />
    </li>
<?php } ?>

I've set up the attribute to use 'Name' for the default sort order in the Attributes settings.

It looks like the variations in the dropdown field observe this sort order (no matter what order I drag/drop the variations in the admin). But the $product->get_available_variations() loop seems to ignore this sort order and use the order of the variations in the admin.

Is there a way I can ensure the above loop ALSO observes the same order as the dropdown?


Solution

  • You can try to solve the problem, only if you are using a single product attribute set for variation for your variable product, by sorting variations from variation attribute terms, like:

    // Get the correct taxonomy for the product attribute set for variation
    $taxonomy   = current( array_keys($product->get_variation_attributes()) ); 
    
    // Get the cached attribute sorted term slugs for the variable product
    $attr_slugs = wc_get_product_terms( $product->get_id(), $taxonomy, ['fields' => 'slugs'] );
    
    $variations = $product->get_available_variations(); // Get available variations
    $sorted_variations = array(); // Initializing
    
    // Sorting Loop 
    foreach( $variations as $variation ) {
        $attr_slug = reset( $variation['attributes'] ); // Get attribute term slug
        $attr_key  = array_search($attr_slug, $attr_slugs); // Get the sorting key from attribute terms array
            
        if ( $attr_key !== false ) {
            $sorted_variations[$attr_key] = $variation; // Add sorted variation
        }
    }
    
    ksort($sorted_variations); // Sort by key (ASC)
    
    echo '<ul>';
    
    // Loop through sorted Variations
    foreach( $sorted_variations as $variation ) { ?>
        <li>
            <img src="<?php echo $variation['image']['src']; ?>" />
        </li>
    <?php }
    
    echo '</ul>';
    

    It should work, displaying the desired sorted variations.


    Change product variations menu order based on variation attribute menu order

    The following will change the variations menu order of a variable product based on the variation attribute (works only on variable products with a unique product attribute set for variations).

    Here, we run this function just before your custom display.

    Note that the function that changes the variations menu order will run just once for each variable product (when visiting the variable product page).

    Add the following function to your child theme functions.php file:

    // Utility function: Change variations menu order based on variation attribute
    function change_variations_menu_order( $product ) {
        // Get the correct taxonomy for the product attribute set for variation
        $taxonomy   = current( array_keys($product->get_variation_attributes()) ); 
    
        // Get the cached attribute sorted term slugs for the variable product
        $attr_slugs = wc_get_product_terms( $product->get_id(), $taxonomy, ['fields' => 'slugs'] );
    
        $variations = $product->get_available_variations(); // Get available variations
        $sorted_variations = array(); // Initializing
    
        // Sorting Loop 
        foreach( $variations as $variation_data ) {
            $attr_slug = reset( $variation_data['attributes'] ); // Get attribute term slug
            $attr_key  = array_search($attr_slug, $attr_slugs); // Get the sorting key from attribute terms array
                
            if ( $attr_key !== false ) {
                $sorted_variations[$attr_key] = $variation_data; // Add sorted variation
            }
        }
    
        ksort($sorted_variations); // Sort by key (ASC)
    
        foreach( $sorted_variations as $key => $variation_data ) {
            $variation_obj = wc_get_product($variation_data['variation_id']);
            $variation_obj->set_props( array( 'menu_order' => $key) );
            $variation_obj->save();
        }
        $product->update_meta_data('variations_sorted', true);
        $product->save();
    }
    

    Use the following code for your custom display on your variable products (it replaces the previous code from this answer):

    if ( ! $product->get_meta('variations_sorted') ) {
        change_variations_menu_order( $product );
    }
    
    echo '<ul>';
    
    // Loop through sorted Variations
    foreach( $product->get_available_variations() as $variation_data ) { ?>
        <li>
            <img src="<?php echo $variation_data['image']['src']; ?>" />
        </li>
    <?php }
    
    echo '</ul>';
    

    It should work as you asked in your comment.