Reputation: 647
i'm working on a site in wordpress and using woocommerce plugin. on my single product page i want to show the related product of same subcategory but unable to do so.
i have a category fall protection with subcategory Harness and Belts and its subcategory is Work Positioning Belts. under that category i have 3 products. i want to show those products as related product.
Here is the code inside my related single-product/related.php
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
global $product, $woocommerce_loop;
$related = $product->get_related( $posts_per_page );
if ( sizeof( $related ) == 0 ) return;
$args = apply_filters( 'woocommerce_related_products_args', array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => $posts_per_page,
'orderby' => $orderby,
'post__in' => $related,
'post__not_in' => array( $product->id )
) );
$products = new WP_Query( $args );
$woocommerce_loop['columns'] = $columns;
if ( $products->have_posts() ) : ?>
<div class="row-fluid">
<div class="related products span9">
<div class="hr"></div>
<h3><?php _e( 'Related Products', 'woocommerce' ); ?></h3>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
</div>
Upvotes: 0
Views: 7565
Reputation: 1
here is my "related.php" code, where i fetch related products from wp_term_relationships of current product,
this works for me and i applied on 2,3 wordpress websites for related products..
* Related Products
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 3.0.0
*/
global $wpdb;
if(! defined('ABSPATH')) exit; // Exit if accessed directly
$product = lucian_get_global_variables('product');
$woocommerce_loop = lucian_get_global_variables('woocommerce_loop');
$lucian_options = lucian_get_global_variables();
//custom code starts here!! fetch term_taxonomy_id
// $terms = wp_get_post_terms( get_the_id(), 'product_cat' );
// echo '<pre>'; print_r($terms); echo '</pre>';
$cats_array = array();
$product_id = $product->id;
$taxonomy_id = "";
// Get categories
$terms = wp_get_post_terms( $product->id, 'product_cat' );
//Select only the category which doesn't have any children
foreach ( $terms as $term ) {
$children = get_term_children( $term->term_id, 'product_cat' );
if ( !sizeof( $children ) )
$cats_array[] = $term->term_id;
$taxonomy_id = $cats_array[0];
}
//custom code Ends here!!
$related = wc_get_related_products( $product->get_id(), $limit = $posts_per_page, $exclude_ids = array() );
if(sizeof($related) == 0) return;
$args = apply_filters( 'woocommerce_related_products_args', array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => $posts_per_page,
'orderby' => $orderby,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $cats_array
),
)
) );
$products = new WP_Query($args);
$woocommerce_loop['name'] = 'related';
$woocommerce_loop['columns'] = apply_filters('woocommerce_related_products_columns', $columns);
//custom code starts here!!!
//fetch Product ids throgh taxonomy id
$results = $wpdb->get_results("SELECT * FROM `wp_term_relationships` WHERE `term_taxonomy_id` = '$taxonomy_id' ");
$tax_id = [];
$count = 1;
// exclude current post id from given array!!
foreach ( $results as $obj ) :
if ($obj->object_id != $product_id) {
if($count <=5)
{
array_push($tax_id,$obj->object_id);
}
$count++;
}
endforeach;
//custom code Ends here!!!
if ( $tax_id ) : ?>
<div class="widget related_products_widget hv vg-icon">
<div class="vg-title"><h3><?php
if(isset($lucian_options['related_icon']) && !empty($lucian_options['related_icon'])) {
echo '<i class="' .esc_attr($lucian_options['related_icon']) .'"></i>';
}?><span><?php echo isset($lucian_options['related_title']) ? esc_html($lucian_options['related_title']) : ''; ?></span></h3></div>
<div class="related products">
<?php woocommerce_product_loop_start(); ?>
<?php foreach ( $tax_id as $id ) : ?>
<?php
$post_object = get_post( $id );
setup_postdata( $GLOBALS['post'] =& $post_object );
wc_get_template_part( 'content', 'product' ); ?>
<?php endforeach; ?>
<?php woocommerce_product_loop_end(); ?>
</div>
</div>
<?php endif;
wp_reset_postdata();
Upvotes: 0
Reputation: 1261
Got a nice solution for WooCommerce > V3.0.0
Just copy the single-product/related.php file from WooCommerce template directory to wocoomerce/templates/single-product/related.php in your theme directory and copy paste the following code to the copied related.php file:
<?php
if (!defined('ABSPATH')) {
exit;
}
global $post, $product;
if (empty($product) || !$product->exists()) {
return;
}
$subcategories_array = array(0);
$all_categories = wp_get_post_terms($product->id, 'product_cat');
foreach ($all_categories as $category) {
$children = get_term_children($category->term_id, 'product_cat');
if (!sizeof($children)) {
$subcategories_array[] = $category->term_id;
}
}
if (sizeof($subcategories_array) == 1) {
return array();
}
$args = array(
'orderby' => 'rand',
'posts_per_page' => 5,
'post_type' => 'product',
'fields' => 'ids',
'meta_query' => $meta_query,
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $subcategories_array
)
)
);
$wp_query = new WP_Query($args);
if ($wp_query->have_posts()):
?>
<section class="related products">
<h2><?php esc_html_e('Related products', 'woocommerce'); ?></h2>
<?php woocommerce_product_loop_start(); ?>
<?php while ($wp_query->have_posts()) : $wp_query->the_post(); ?>
<?php
global $post, $product;
$post_object = get_post($product->get_id());
setup_postdata($GLOBALS['post'] = & $post_object);
wc_get_template_part('content', 'product');
?>
<?php endwhile; ?>
<?php woocommerce_product_loop_end(); ?>
</section>
<?php
endif;
wp_reset_postdata();
Upvotes: 0
Reputation: 4597
you need to modify related.php template file. PATH: your-theme/woocommerce/single-product/related.php
Change $args to,
$args = apply_filters( 'woocommerce_related_products_args', array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => $posts_per_page,
'orderby' => $orderby,
'post__not_in' => array( $product->id ),
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $cats_array
),
)
) );
where $cats_array is,
$cats_array = array(0);
// Get product categories
$terms = wp_get_post_terms( $product->id, 'product_cat' );
//Select only the category which doesn't have any children
if( sizeof( $terms ) ){
foreach ( $terms as $term ) {
$children = get_term_children( $term->term_id, 'product_cat' );
if ( !sizeof( $children ) )
$cats_array[] = $term->term_id;
}
}
and remove/comment following lines,
$related = $product->get_related( $posts_per_page );
if ( sizeof( $related ) == 0 ) return;
Upvotes: 1
Reputation: 1
I struggled with this for way longer than I needed to.
Find my final related.php file. You can paste this over thte generic template file in your child theme.
<?php
/**
* Related Products
*
* @author WooThemes
* @package WooCommerce/Templates
* @version 1.6.4
*/
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
if ( is_singular('product') ) {
global $post;
// get categories
$terms = wp_get_post_terms( $post->ID, 'product_cat' );
foreach ( $terms as $term ) $cats_array[] = $term->term_id;
$query_args = array( 'orderby' => 'rand', 'post__not_in' => array( $post->ID ), 'posts_per_page' => 4, 'no_found_rows' => 1, 'post_status' => 'publish', 'post_type' => 'product', 'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $cats_array
)));
$r = new WP_Query($query_args);
if ($r->have_posts()) { ?>
<div class="related products">
<h2><?php _e( 'Related Products', 'woocommerce' ); ?></h2>
<?php woocommerce_product_loop_start(); ?>
<?php while ($r->have_posts()) : $r->the_post(); global $product; ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
</div>
<?php
wp_reset_query();
}
}
Upvotes: 0
Reputation: 21
The above works on latest WordPress/WooCommerce (Nov 2014), but you need to override related.php at /wp-content/themes/my-child-theme/woocommerce/single-product/related.php and it needs to look like this:
if ( ! defined( 'ABSPATH' ) ) exit; // Exit if accessed directly
global $product, $woocommerce_loop;
if ( empty( $product ) || ! $product->exists() ) {
return;
}
$related = $product->get_related( $posts_per_page );
if ( sizeof( $related ) == 0 ) return;
$args = apply_filters('woocommerce_product_related_posts', array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => $posts_per_page,
'orderby' => $orderby,
'post__in' => custom_related_products($product),
'post__not_in' => array($product->id)
) );
$products = new WP_Query( $args );
$woocommerce_loop['columns'] = $columns;
if ( $products->have_posts() ) : ?>
<div class="related products">
<h2>You Might Also Like...</h2>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
</div>
<?php endif;
wp_reset_postdata();
Upvotes: 1
Reputation: 561
Not sure if this is the best way of doing it but I did this way.
I added a function for getting the products of the same sub category
function custom_related_products($product){
global $woocommerce;
// Related products are found from category and tag
$tags_array = array(0);
$cats_array = array(0);
// Get tags
$terms = wp_get_post_terms($product->id, 'product_tag');
foreach ( $terms as $term ) $tags_array[] = $term->term_id;
// Get categories
$terms = wp_get_post_terms($product->id, 'product_cat');
foreach ( $terms as $key => $term ){
$check_for_children = get_categories(array('parent' => $term->term_id, 'taxonomy' => 'product_cat'));
if(empty($check_for_children)){
$cats_array[] = $term->term_id;
}
}
// Don't bother if none are set
if ( sizeof($cats_array)==1 && sizeof($tags_array)==1 ) return array();
// Meta query
$meta_query = array();
$meta_query[] = $woocommerce->query->visibility_meta_query();
$meta_query[] = $woocommerce->query->stock_status_meta_query();
$meta_query = array_filter( $meta_query );
// Get the posts
$related_posts = get_posts( array(
'orderby' => 'rand',
'posts_per_page' => $limit,
'post_type' => 'product',
'fields' => 'ids',
'meta_query' => $meta_query,
'tax_query' => array(
'relation' => 'OR',
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => $cats_array
),
array(
'taxonomy' => 'product_tag',
'field' => 'id',
'terms' => $tags_array
)
)
) );
$related_posts = array_diff( $related_posts, array( $product->id ), $product->get_upsells() );
return $related_posts;
}
And then in related.php do this
global $product, $woocommerce_loop;
if ( sizeof( $related ) == 0 ) return;
$args = apply_filters('woocommerce_product_related_posts', array(
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'no_found_rows' => 1,
'posts_per_page' => $posts_per_page,
'orderby' => $orderby,
'post__in' => custom_related_products($product),
'post__not_in' => array($product->id)
) );
$products = new WP_Query( $args );
$woocommerce_loop['columns'] = $columns;
if ( $products->have_posts() ) : ?>
<div class="related products">
<h2><?php _e( 'Related Products', 'woocommerce' ); ?></h2>
<?php woocommerce_product_loop_start(); ?>
<?php while ( $products->have_posts() ) : $products->the_post(); ?>
<?php woocommerce_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php do_action('add_all_to_cart_at_once_for_related_products'); ?>
<?php woocommerce_product_loop_end(); ?>
</div>
<?php endif;
wp_reset_postdata();
I guess you can call the same logic in related.php to make it simpler but I prefer to keep it separate. Hope that helps!
Upvotes: 2