JI-Web
JI-Web

Reputation: 533

woocommerce shop product variations

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.

Upvotes: 5

Views: 7825

Answers (3)

KARTIK KUMAR
KARTIK KUMAR

Reputation: 9

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

Upvotes: 0

Rohit Kaushik
Rohit Kaushik

Reputation: 1302

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
}

Upvotes: 3

Thomas Stubbe
Thomas Stubbe

Reputation: 1985

$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/

Upvotes: 0

Related Questions