0

I've found this great solution to display related products based on a product attribute, but additionally we would like to do the same with our upsells .

What I've tried so far doesn't work yet because I believe we have to add some additonal information as the related_products function is not the same as upsells.

add_filter( 'woocommerce_upsell_products', 'upsell_products_by_attribute', 10, 3 );
function upsell_products_by_attribute( $upsells, $product_id, $args ) {
    $taxonomy   = 'pa_attribute';

    $term_slugs = wp_get_post_terms( $product_id, $taxonomy, ['fields' => 'slugs'] );

    if ( empty($term_slugs) )
        return $upsells;

    $posts_ids = get_posts( array(
        'post_type'            => 'product',
        'ignore_sticky_posts'  => 1,
        'posts_per_page'       => 6,
        'post__not_in'         => array( $product_id ),
        'tax_query'            => array( array(
            'taxonomy' => $taxonomy,
            'field'    => 'slug',
            'terms'    => $term_slugs,
        ) ),
        'fields'  => 'ids',
        'orderby' => 'rand',
    ) );

    return count($posts_ids) > 0 ? $posts_ids : $upsells;
}

So I wonder if there is any possibility to do the same with the upsell section.

Panda
  • 6,955
  • 6
  • 40
  • 55
Jonas
  • 3
  • 2
  • I'm afraid. The Upsell and Cross-sell work with a manual selection from the product backend page. You cannot specify them using the function. Otherwise, it will act as a related product that works based on something associated with the current product, either category/tag/attributes, etc. But yes, if you want to show the Upsell products from those you have already selected manually from the product page and now want to filter them by attributes, then it might be possible to use functions. – Showhan Ahmed Dec 03 '22 at 04:28
  • Thanks a lot @ShowhanAhmed, that clarifies the issue quite well. I might try some other solutions instead. – Jonas Dec 03 '22 at 06:56

1 Answers1

1

You can remove the default action hook woocommerce_after_single_product_summary and add it again and you can customize upsells products. check the below code. code will go into your active theme functions.php file.

Change $taxonomy = 'pa_color'; to your custom taxonomy.

function modify_woocommerce_upsell_display_based_on_attribute( $limit = '-1', $columns = 4, $orderby = 'rand', $order = 'desc' ){
    
    remove_action( 'woocommerce_after_single_product_summary', 'woocommerce_upsell_display', 15 );

    global $product;

    if ( ! $product ) {
        return;
    }

    // Handle the legacy filter which controlled posts per page etc.
    $args = apply_filters(
        'woocommerce_upsell_display_args',
        array(
            'posts_per_page' => $limit,
            'orderby'        => $orderby,
            'order'          => $order,
            'columns'        => $columns,
        )
    );

    wc_set_loop_prop( 'name', 'up-sells' );
    wc_set_loop_prop( 'columns', apply_filters( 'woocommerce_upsells_columns', isset( $args['columns'] ) ? $args['columns'] : $columns ) );

    $orderby = apply_filters( 'woocommerce_upsells_orderby', isset( $args['orderby'] ) ? $args['orderby'] : $orderby );
    $order   = apply_filters( 'woocommerce_upsells_order', isset( $args['order'] ) ? $args['order'] : $order );
    $limit   = apply_filters( 'woocommerce_upsells_total', isset( $args['posts_per_page'] ) ? $args['posts_per_page'] : $limit );

    // set your custom taxonomy here.
    $taxonomy   = 'pa_color';

    $term_slugs = wp_get_post_terms( $product->get_id(), $taxonomy, ['fields' => 'slugs'] );

    $posts_ids = get_posts( array(
        'post_type'            => 'product',
        'ignore_sticky_posts'  => 1,
        'posts_per_page'       => 6,
        'post__not_in'         => array( $product->get_id() ),
        'tax_query'            => array( array(
            'taxonomy' => $taxonomy,
            'field'    => 'slug',
            'terms'    => $term_slugs,
        ) ),
        'fields'  => 'ids',
        'orderby' => 'rand',
    ) );

    if( !empty( $posts_ids ) ){

        // Get visible upsells then sort them at random, then limit result set.
        $upsells = wc_products_array_orderby( array_filter( array_map( 'wc_get_product', $posts_ids ), 'wc_products_array_filter_visible' ), $orderby, $order );
        $upsells = $limit > 0 ? array_slice( $upsells, 0, $limit ) : $upsells;

        wc_get_template(
            'single-product/up-sells.php',
            array(
                'upsells'        => $upsells,

                // Not used now, but used in the previous version of up-sells.php.
                'posts_per_page' => $limit,
                'orderby'        => $orderby,
                'columns'        => $columns,
            )
        );
    }

}

add_action( 'woocommerce_after_single_product_summary', 'modify_woocommerce_upsell_display_based_on_attribute', 15 );
Bhautik
  • 11,125
  • 3
  • 16
  • 38