Search code examples
phpwordpresswoocommercehtml-tableproduct-variations

Woocommerce Custom Variations html table only showing columns with values


Based on WooCommerce variable products: Display some variations values in an HTML table code answer, I have this table showing correctly, but I only want the attribute columns to show if they exist, how can I alter this to do so?

E.g. If there are any variations that have 'Techonology' as an option then show the 'Technology' column, if not hide it.

add_action( 'woocommerce_after_single_product_summary', 'custom_table_after_single_product' );
function custom_table_after_single_product(){
    global $product;
if( ! $product->is_type('variable')) return; 

    $available_variations = $product->get_available_variations();

    if( count($available_variations) > 0 ){

        $output = '<table>
            <thead>
                <tr>
                    <th>'. __( 'Image', 'woocommerce' ) .'</th>
                    <th>'. __( 'SKU', 'woocommerce' ) .'</th>
                    <th>'. __( 'Colour', 'woocommerce' ) .'</th>
                    <th>'. __( 'Technology', 'woocommerce' ) .'</th>
                    <th>'. __( 'Positive/Negative', 'woocommerce' ) .'</th>
                </tr>
            </thead>
            <tbody>';

        foreach( $available_variations as $variation ){
            // Get an instance of the WC_Product_Variation object
            $product_variation = wc_get_product($variation['variation_id']);

            $output .= '
            <tr>
                <td>'. $product_variation->get_image('snippets') .'</td>
                <td>'. $product_variation->get_sku() .'</td>
                <td>'. $product_variation->get_attribute('pa_colour_range') .'</td>
                <td>'. $product_variation->get_attribute('pa_technology') .'</td>
                <td>'. $product_variation->get_attribute('pa_posneg') .'</td>
                
            </tr>';
        }
        $output .= '
            </tbody>
        </table>';

        echo $output;
    }
}

Solution

  • Try the following, that will display each table column only if there are values for it:

    add_action( 'woocommerce_after_single_product_summary', 'custom_table_after_single_product' );
    function custom_table_after_single_product(){
        global $product;
    
        if( ! $product->is_type('variable')) return;
        
        // Get available variations
        $variations = $product->get_available_variations('object');       
    
        if( count($variations) > 0 ){
            // Set the table columns heading in an array
            $table_head = array(
                'image'         => __( 'Image', 'woocommerce' ),
                'sku'           => __( 'SKU', 'woocommerce' ),
                'colour'        => __( 'Colour', 'woocommerce' ),
                'technology'    => __( 'Technology', 'woocommerce' ),
                'posneg'        => __( 'Positive/Negative', 'woocommerce' ),
            );
    
            $table_columns = array_keys($table_head);
            $table_data = $variation_ids = array(); // Initializing
    
            // Set the table columns values in an array sorted by column
            foreach ( $variations as $variation ) {
                $variation_id    = $variation->get_id();
                $variation_ids[] = $variation_id;
    
                if ( $image = $variation->get_image('snippets') ) {
                    $table_data['image'][$variation_id] = $image;
                }
                if ( $sku = $variation->get_sku() ) {
                    $table_data['sku'][$variation_id] = $sku;
                }
                if ( $colour = $variation->get_attribute('pa_colour_range') ) {
                    $table_data['colour'][$variation_id] = $colour;
                }
                if ( $technology = $variation->get_attribute('pa_technology') ) {
                    $table_data['technology'][$variation_id] = $technology;
                }
                if ( $posneg = $variation->get_attribute('pa_posneg') ) {
                    $table_data['posneg'][$variation_id] = $posneg;
                }
            }
    
            // Output start
            $output = '<table>
                <thead>
                    <tr>';
    
                    // Loop through table head columns
                    foreach ( $table_head as $column => $column_label ) {
                        if( isset($table_data[$column]) ) {
                            $output .= '<th>'. $column_label .'</th>';
                        }
                    }
                    $output .= '</tr>
                </thead>
                <tbody>';
    
            // Loop through variations Ids
            foreach( $variation_ids as $variation_id ){
                $output .= '<tr>';
    
                // Loop through table columns
                foreach ( $table_columns as $column ) {
                    if( isset($table_data[$column]) ) {
                        $output .= '<td>'. $table_data[$column][$variation_id] .'</td>';
                    }
                }
                $output .= '</tr>';
            }
            $output .= '
                </tbody>
            </table>';
    
            echo $output;
        }
    }
    

    Code goes in functions.php file of your active child theme (or active theme). Tested and works.