Skip to content

Instantly share code, notes, and snippets.

@simonlk
Last active February 21, 2022 20:27
Show Gist options
  • Save simonlk/3967956 to your computer and use it in GitHub Desktop.
Save simonlk/3967956 to your computer and use it in GitHub Desktop.
Output Woocommerce product variations as a table within a tab on the single product page
// Add to functions.php
/*===================================================
Created by sk from Renegade Empire with help
from these sources:
http://docs.woothemes.com/document/editing-product-data-tabs/
http://www.sean-barton.co.uk/2013/03/remove-woocommerce-20-reviews-tab/#.UYnWe7XfB6N
http://www.sean-barton.co.uk/2013/03/sb-add-woocommerce-tabs-wordpress-plugin/#.UYrYL7XfB6M
====================================================*/
/*===================================================
Options
====================================================*/
$re_wcvt_options = array(
'tab_title' => 'Product Variations', // change the tile of the tab
'sku_title' => 'REF #', // change the sku column heading
'show_price' => 'yes', // show price column: yes or no
'show_description' => 'yes', // show description column: yes or no
'tab_priority' => '5', // 5 is good to make the tab appear first
);
/*===================================================
Add the tab
====================================================*/
add_filter( 'woocommerce_product_tabs', 're_woo_product_variations_tab' );
function re_woo_product_variations_tab() {
global $woocommerce, $product, $post, $re_wcvt_options;
// $available_variations = $product->get_available_variations();
// $attributes = $product->get_attributes();
if (is_product() and $product->product_type == 'variable') {
// Adds the new tab
$tabs['variations_table'] = array(
'title' => __( $re_wcvt_options['tab_title'], 'woocommerce' ),
'priority' => 50,
'callback' => 're_woo_product_variations_tab_content'
);
return $tabs;
}
}
/*===================================================
Build the tab content
====================================================*/
function re_woo_product_variations_tab_content() {
global $woocommerce, $product, $post, $re_wcvt_options;
$available_variations = $product->get_available_variations();
$attributes = $product->get_attributes();
// The new tab content
//echo '<h2>Product Variations</h2>';
//echo '<p>Here\'s your new product tab.</p>';
?>
<table class="table table-striped table-hover table-bordered varations-table tablesorter">
<thead>
<tr>
<th><?php echo $re_wcvt_options['sku_title']; ?></th>
<?php
// Show description if option is set to yes
if ($re_wcvt_options['show_description'] == 'yes') : ?>
<th>Description</th>
<?php endif; ?>
<?php foreach ( $attributes as $name => $options) :?>
<th>
<?php
//echo $woocommerce->attribute_label($name);
$attr_name = $options['name'];
if (0 === strpos($attr_name, 'pa_')){
$attr_name = $woocommerce->attribute_label($attr_name);
}
echo $attr_name;
?>
</th>
<?php endforeach;?>
<?php
// Show price if option is set to yes
if ($re_wcvt_options['show_price'] == 'yes') : ?>
<th>Price</th>
<?php endif; ?>
<th class="var-qty">&nbsp;</th>
<th class="var-add-to-cart">&nbsp;</th>
</tr>
</thead>
<tbody>
<?php
/*
echo '<pre>';
print_r($re_wcvt_options);
echo '</pre>';
*/
?>
<?php foreach ($available_variations as $prod_variation) : ?>
<?php
// get some vars to work with
$post_id = $prod_variation['variation_id'];
$post_object = get_post($post_id);
//echo '<pre>';
//print_r($prod_variation);
//echo '</pre>';
?>
<tr>
<td>
<?php
// echo substr($prod_variation['sku'], 5, 100) ; // output SKU but trim the first part that is added
echo $prod_variation['sku'];
?>
</td>
<?php
// Show description if option is set to yes
if ($re_wcvt_options['show_description'] == 'yes') : ?>
<td>
<?php
$variation_desc = get_post_meta( $post_object->ID, '_description', true);
if ( !empty($post_object->post_content)){
$variation_desc = $post_object->post_content; // post content
} elseif (!empty($variation_desc)) {
$variation_desc = get_post_meta( $post_object->ID, '_description', true); // get meta description
} else {
$variation_desc = get_the_title($product->id); // parent title
}
echo $variation_desc;
?>
</td>
<?php endif; ?>
<?php foreach ($prod_variation['attributes'] as $attr_name => $attr_value) : ?>
<td>
<?php
// Get the correct variation values
if (strpos($attr_name, '_pa_')){ // variation is a pre-definted attribute
$attr_name = substr($attr_name, 10);
$attr = get_term_by('slug', $attr_value, $attr_name);
$attr_value = $attr->name;
} else { // variation is a custom attribute
//$attr = maybe_unserialize( get_post_meta( $post->ID, '_product_attributes' ) );
//$attr_value = var_dump($attr);
//$attr = get_term_by('slug', $attr_value, $attr_name);
//$attr_value = $attr->name;
}
echo $attr_value;
?>
</td>
<?php endforeach;?>
<?php
// Show price if option is set to yes
if ($re_wcvt_options['show_price'] == 'yes') : ?>
<td><?php echo get_woocommerce_currency_symbol() . get_post_meta( $post_object->ID, '_price', true); ?></td>
<?php endif; ?>
<form action="<?php echo do_shortcode('[add_to_cart_url id="'.$product->id.'"]'); ?>" class="variations_form cart" method="post" enctype="multipart/form-data" data-product_id="<?php echo $product->id; ?>">
<td>
<?php woocommerce_quantity_input(); ?>
</td>
<td>
<input type="hidden" name="variation_id" value="<?php echo $post_id; ?>">
<?php foreach ($prod_variation['attributes'] as $attr_name => $attr_value) : ?>
<input type="hidden" name="<?php echo sanitize_title($attr_name); ?>" value="<?php echo $attr_value ;?>">
<?php endforeach;?>
<button type="submit" class="btn btn-small button add-to" type="button">Add to cart</button>
</td>
</form>
</tr>
<?php endforeach;?>
</tbody>
</table>
<?php
//echo '<pre>';
//print_r($prod_variation['attributes']);
//echo '</pre>';
?>
<?php
}
/*===================================================
Tab Position
====================================================*/
add_filter( 'woocommerce_product_tabs', 're_woo_move_variation_table_tab', 98);
function re_woo_move_variation_table_tab($tabs) {
global $re_wcvt_options;
if ($tabs['variations_table']) {
$tabs['variations_table']['priority'] = $re_wcvt_options['tab_priority'];
}
return $tabs;
}
@emilysnothere
Copy link

This worked for me replace line 169 to 181 above with the following:


<form class="variations_form cart" method="post" enctype='multipart/form-data' data-product_id="<?php echo $product->id; ?>" data-product_variations="<?php echo esc_attr( json_encode( $available_variations ) ) ?>">

    <td>
    <?php woocommerce_quantity_input(); ?>
    </td>
    <td>

    <input type="hidden" name="add-to-cart" value="<?php echo $product->id; ?>" />
    <input type="hidden" name="product_id" value="<?php echo $product->id; ?>" />
    <input type="hidden" name="variation_id" value="<?php echo $post_id; ?>" />
    <div class="variations_button">
        <?php foreach ($prod_variation['attributes'] as $attr_name => $attr_value) : ?>
            <input type="hidden" name="<?php echo sanitize_title($attr_name); ?>" value="<?php echo $attr_value ;?>">
            <?php endforeach;?>
        <button type="submit" class="btn btn-small button add-to"><?php echo $product->single_add_to_cart_text(); ?></button>
    </div>  
    </td>
</form>

@tagplus5
Copy link

emilysnothere, thanks, now it works. Woocommerce 2.1.6

@mediavinc
Copy link

Hi,
Thanks a lot for this code. I've just install it on a fresh Woocommerce 2.1.12 (and WP 3.9.2) and it does the job!
However, I am facing a problem regarding the attributes display order...

I have created three predefined attributes (with custom ordering) and I have created a variable product with some variations.
When I display the product page, I have the table headings <th> that are in the correct order but the data below in the table row <td> are not matching...
In fact, when I am in the product edit page, on the attributes tab, I drag and drop the attributs to set the order and save the product. When I reload the product page on frontend, the heading have changed but not the columns below.

Does anyone have a fix?

Here are the two loops in my function.php:

<?php foreach ($attributes as $name => $options) :?>
  <th>
                        <?php 
                            $attr_name = $options['name'];
                            if (0 === strpos($attr_name, 'pa_')){
                                $attr_name = $woocommerce->attribute_label($attr_name);
                            }
                            echo $attr_name;
                        ?>
  </th>
<?php endforeach;?>

and

<?php foreach ($prod_variation['attributes'] as $attr_name => $attr_value) : ?>
  <td>
                        <?php
                            if (strpos($attr_name, '_pa_')){ // variation is a pre-definted attribute
                                $attr_name = substr($attr_name, 10);
                                $attr = get_term_by('slug', $attr_value, $attr_name);
                                $attr_value = $attr->name;
                            } 

                            else { // variation is a custom attribute
                                //$attr = maybe_unserialize( get_post_meta( $post->ID, '_product_attributes' ) );
                                //$attr_value = var_dump($attr);
                                //$attr = get_term_by('slug', $attr_value, $attr_name);
                                //$attr_value = $attr->name;
                            }
                            echo str_replace(array('-','_'), ' ', $attr_value);

                        ?>
  </td>
<?php endforeach;?>

@actua
Copy link

actua commented Sep 12, 2014

Could it be obtain the variations in a dropdown?
For example:

<select .... >
    <option ...> Red Color + Size XL: (12,00 €)  
    ...
    ...
</select>

@onestopdive
Copy link

how to show the stock level of each product ?

@davemoz
Copy link

davemoz commented Nov 22, 2014

I'm trying to display a plain-text list of product attributes (either names or IDs), such as colors, underneath each product on the archive/catalog page. Which part of this code would I use to do this? I know it's in there, but all I need is the attributes plain-text output. Anyone know?

Copy link

ghost commented Jan 5, 2015

Hi i'm currently having a problem to display value of the attributes..

At the moment it's working nicely except that the variation values output the sanitized version i.e. '3.4 x 2.3' outputs as '34-23'

echo str_replace(array('-','_'), ' ', $attr_value) <-- i did use this but it's not really perfect since there are some '.' not showing up as in 'slug' of the term

Anyone have found the work arround for it? -thx in advance-

@RonR-WebDesign
Copy link

Has anyone figured out how to do only one "Add to Cart" button? Fill in the quantities and press one button would be awesome!

@alison18
Copy link

This is a great feature & has been working for me until I Updated Wordpress & Woocommerce.

I think this is the error I am getting


Fatal error: Call to undefined function add_filter() in [...][...] on line 34

If someone could help me I would really appreciate it! Thanks

@Namennaj
Copy link

Hi @renegadesk. Please look at line 178 of your code. Your Button have two types in there. That may be causing your issue.

@ignacioazzi
Copy link

Has anyone been able to make this work with the "Add to Cart" button using an Ajax Call? Everytime I hit the "Add to Cart" button the page refresh and it changes to the Description Tab.

@mattbee
Copy link

mattbee commented Mar 18, 2016

The error "Call to undefined method WooCommerce::attribute_label()..." can be fixed by updating the name of the method on lines 83 and 86, to $woocommerce->**wc_**attribute_label($name)

@Winsiders
Copy link

Winsiders commented Sep 29, 2017

you need to add $tabs in this function, if not, only the tab in the function will be display :
function re_woo_product_variations_tab( $tabs ) {
And $woocommerce is depreciate in WC 3+ - use WC()

@plumdm
Copy link

plumdm commented Feb 9, 2018

This is great, thanks! Not sure if you ended up doing it, but you should definitely package this into a plugin.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment