3
votes

I would like to show all products and their variations on the Wp/Woocommerce /shop/ page. (/woocommerce/archive-product.php). The process I'm describing below is my attempt at getting this to work. Alternatives are welcome.

What is the norm: Product A and Product B show on the site. Product A has 'ad to cart' button. Product B has 'Select Options' button.

What I'm after: Product A is a 'simple' product and shows on the shop page Product B is a 'variable' product and has 2 combinations (Black/Blue). An Add to cart button adds this variation to the cart

I would like to show 3 products on the shop page equaling 1* product A and 2* product B.

So far I've pulled out if the product is variable some basic details about this product variation but I cannot seem to find the thumbnail?

$postId = get_the_ID();
$args = array(
    'post_type'     => 'product_variation',
    'post_status'   => array( 'private', 'publish' ),
    'numberposts'   => -1,
    'orderby'       => 'menu_order',
    'order'         => 'asc',
    'post_parent'   => $postId
);
$variations = get_posts( $args );
//var_dump($variations);

//$p = get_post_meta($postId, '_product_attributes', true);  // return pa_flavor
//var_dump($p);

if(!empty($variations)) {
    foreach ($variations as $variation) {

        $vari = new WC_Product_Variation($variation->ID);
        $availableAttr = $vari->get_attribute('Flavour');
        $flavour = get_post_meta($variation->ID, 'attribute_pa_flavour', true);

Therefore, I can get the attribute for 'flavor' and am looking for the thumbnail that is defined for each variation...? Any help/pointers to where this could be are appreciated.

Also [ probably my lack of understanding of Wordpress ] I cannot seem to pass/access variables in wc_get_template(). This is probably a secondary question but still related to the fundamental issue of displaying both single and variation products on one page.

remove_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price', 10 );
add_action( 'woocommerce_after_shop_loop_item_title', 'woocommerce_template_loop_price_variation', 10 );

if ( ! function_exists( 'woocommerce_template_loop_price_variation' ) ) {
    function woocommerce_template_loop_price_variation($prodVar=array()) {

        if(empty($prodVar) || $prodVar['product_type'] == 'simple') {
            wc_get_template( 'loop/price.php' );
        }  else {
            wc_get_template( 'loop/price-variation.php' , $prodVar );
        }
    }
}

And in /price-variation.php (copy of price.php woocommerce base)

global $product;
var_dump($prodVar);  // PRODUCED NOTICE to undefined variable??? 
<?php if ( $price_html = $product->get_price_html() ) : ?>
    <span class="price"><?php echo $price_html; ?></span>
<?php endif; ?>

I don't want it global...? or is this the only way?

Any help or recommendations appreciated.

3
$variation->get_image() should get a variation object's thumbnail. Also, I think you can change new WC_Product_Variation to wc_get_product().helgatheviking
I've actually been thinking about building a plugin to do this, but I've gotten a little stuck on what happens with multiple attributes. For example: wouldn't want to show Black Large and Black Small if they have the same thumbnail. Curious if you have any thoughts on how to select which variations to add to the loop? How would it work easiest for you?helgatheviking
Thanks Helgatheviking. I haven't given this more thought at this stage because we've gone down another route. Eventually I would like to revisit this and a plugin would be awesome. Thanks for your reply.JI-Web
I will probably keep tinkering with it as I have time, but so far it looks like some complicated custom queries will have to happen.helgatheviking

3 Answers

0
votes
$thumb_image = get_the_post_thumbnail($variable_id, $size);

You can override the product thumbnail (in functions.php) for the loop. If the variation_id is globally set in case of a variation and null in case of a simple product, you can do:

remove_action('woocommerce_before_shop_loop_item_title', 'woocommerce_template_loop_product_thumbnail', 10);
function own_woocommerce_thumbnail() {
    global $product, $woocommerce, $variable_id;

    $items_in_cart = array();

    if ($woocommerce->cart->get_cart() && is_array($woocommerce->cart->get_cart())) {
        foreach ($woocommerce->cart->get_cart() as $cart) {
            $items_in_cart[] = $cart['product_id'];
        }
    }

    $id = get_the_ID();
    $in_cart = in_array($id, $items_in_cart);
    $size = 'medium';
    if ($variable_id) {
        $thumb_image = get_the_post_thumbnail($variable_id, $size);
    } else {
        $thumb_image = get_the_post_thumbnail($id, $size);
    }

    echo '<span class="featured-image">';
    echo $thumb_image;
    echo '<span class="cart-loading" style="display: none">';
    if ($in_cart) {
        echo '<i class="fa fa-check-square-o"></i>';
    } else {
        echo '<i class="fa fa-spinner"></i>';
    }
    echo '</span></span>';
}
add_action('woocommerce_before_shop_loop_item_title', 'own_woocommerce_thumbnail', 10);

Note: This will brake pagination, since one product will be displayed multiple times on the product page. Note 2: You'll need to write some jquery for the hover actions to fix "add to cart"

Have you found a decent solution for this problem?

I've posted a similar question here, which may give you more insights: Display all products and variations on the shop page, while maintaining pagination

Edit: There is a plugin 'Woocommerce Show Single Variations' which works. It used to be free, but not anymore: https://iconicwp.com/products/woocommerce-show-single-variations/

0
votes

Paste this code in your theme functions.php

/**
 * Replace add to cart button in the loop.
 */
function iconic_change_loop_add_to_cart() {
    remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 );
    add_action( 'woocommerce_after_shop_loop_item', 'iconic_template_loop_add_to_cart', 10 );
}

add_action( 'init', 'iconic_change_loop_add_to_cart', 10 );

/**
 * Use single add to cart button for variable products.
 */
function iconic_template_loop_add_to_cart() {
    global $product;

    if ( ! $product->is_type( 'variable' ) ) {
        woocommerce_template_loop_add_to_cart();
        return;
    }

    remove_action( 'woocommerce_single_variation', 'woocommerce_single_variation_add_to_cart_button', 20 );
    add_action( 'woocommerce_single_variation', 'iconic_loop_variation_add_to_cart_button', 20 );

    woocommerce_template_single_add_to_cart();
}

/**
 * Customise variable add to cart button for loop.
 *
 * Remove qty selector and simplify.
 */
function iconic_loop_variation_add_to_cart_button() {
    global $product;

    ?>
    <div class="woocommerce-variation-add-to-cart variations_button">
        <button type="submit" class="single_add_to_cart_button button"><?php echo esc_html( $product->single_add_to_cart_text() ); ?></button>
        <input type="hidden" name="add-to-cart" value="<?php echo absint( $product->get_id() ); ?>" />
        <input type="hidden" name="product_id" value="<?php echo absint( $product->get_id() ); ?>" />
        <input type="hidden" name="variation_id" class="variation_id" value="0" />
    </div>
    <?php
}
0
votes

add_action( 'woocommerce_before_shop_loop', 'handsome_bearded_guy_select_variations' );

function handsome_bearded_guy_select_variations() { remove_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_loop_add_to_cart', 10 ); add_action( 'woocommerce_after_shop_loop_item', 'woocommerce_template_single_add_to_cart', 30 ); }

Add this to your functions.php file and You are done