How to implement pagination is custom shortcode? - php

I am using woocommerce 3.0.3, wordpress 4.7.3 .
I have created a custom shortocde with code below ( taken reference from default [products] shortcode of woocommerce ), but the pagination is not working, page 2 going blank .
<?php
add_shortcode('poster_products', 'poster_products');
if ( ! function_exists('poster_products') ){
function poster_products( $atts ) {
$atts = shortcode_atts( array(
'columns' => '4',
'orderby' => 'title',
'order' => 'asc',
'ids' => '',
'skus' => '',
'posts_per_page' => -1
), $atts, 'products' );
$query_args = array(
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'orderby' => $atts['orderby'],
'order' => $atts['order'],
'posts_per_page' => $atts['posts_per_page'],
'paged' => max( 1, get_query_var( 'paged' ) ),
'post__in' => $atts['ids'],
//'meta_query' => WC()->query->get_meta_query(),
//'tax_query' => WC()->query->get_tax_query(),
);
if ( ! empty( $atts['skus'] ) ) {
$query_args['meta_query'][] = array(
'key' => '_sku',
'value' => array_map( 'trim', explode( ',', $atts['skus'] ) ),
'compare' => 'IN',
);
}
if ( ! empty( $atts['ids'] ) ) {
$query_args['post__in'] = array_map( 'trim', explode( ',', $atts['ids'] ) );
}
return poster_product_loop( $query_args, $atts, 'products' );
}
}
if ( ! function_exists('poster_product_loop') ){
function poster_product_loop( $query_args, $atts, $loop_name ) {
global $woocommerce_loop;
$columns = absint( $atts['columns'] );
$woocommerce_loop['columns'] = $columns;
$woocommerce_loop['name'] = $loop_name;
$query_args = apply_filters( 'woocommerce_shortcode_poster_product_query', $query_args, $atts, $loop_name );
$transient_name = 'wc_loop' . substr( md5( json_encode( $query_args ) . $loop_name ), 28 ) . WC_Cache_Helper::get_transient_version( 'product_query' );
$products = get_transient( $transient_name );
if ( false === $products || ! is_a( $products, 'WP_Query' ) ) {
$products = new WP_Query( $query_args );
set_transient( $transient_name, $products, DAY_IN_SECONDS * 30 );
}
ob_start();
if ( $products->have_posts() ) {
?>
<?php do_action( "woocommerce_shortcode_before_{$loop_name}_loop", $atts ); ?>
<?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(); ?>
<?php do_action( "woocommerce_shortcode_after_{$loop_name}_loop", $atts ); ?>
<?php
do_action('woocommerce_pagination_after_poster_product_loop', $products);
} else {
do_action( "woocommerce_shortcode_{$loop_name}_loop_no_results", $atts );
}
woocommerce_reset_loop();
wp_reset_postdata();
do_action( 'woocommerce_after_shop_loop' );
return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
}
}
add_action('woocommerce_pagination_after_poster_product_loop', 'woocommerce_pagination_after_poster_product_loop');
if ( ! function_exists( 'woocommerce_pagination_after_poster_product_loop' ) ) {
function woocommerce_pagination_after_poster_product_loop($products) {
//wc_get_template( 'loop/pagination.php' );
if ( ! defined( 'ABSPATH' ) ) {
exit; // Exit if accessed directly
}
global $wp_query;
if ( $products->max_num_pages <= 1 ) {
return;
}
?>
<nav class="woocommerce-pagination">
<?php
echo paginate_links( apply_filters( 'woocommerce_pagination_args', array(
'base' => esc_url_raw( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) ),
'format' => '?paged=%#%',
'add_args' => false,
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $products->max_num_pages,
'prev_text' => '←',
'next_text' => '→',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3,
) ) );
} ?>
</nav>
<?php
}
Pagination creating url structure like /page/2/
Page 2 source code displaying
</nav>
<!DOCTYPE html>
and
if ( ! function_exists('poster_products') ){
echo var_dump(get_query_var( 'page' )); // ""
echo var_dump(get_query_var( 'paged' )); // ""
and
function poster_products( $atts ) {
return "poster_products getting called";
returning nothing so poster_products is not getting called on page 2.

It has been more than a month but at that time, I was done with this code which is working for me now.
/**
* Creates poster_products shortcode
*/
add_shortcode('poster_products', 'poster_products');
if ( ! function_exists('poster_products') ){
function poster_products( $atts ) {
$atts = shortcode_atts( array(
'columns' => '3',
'orderby' => 'title',
'meta_key' => '',
'order' => 'asc',
'ids' => '',
'skus' => '',
'posts_per_page' => -1
), $atts, 'products' );
$page_number = is_front_page() ? max( 1, get_query_var( 'page' ) ) : max( 1, get_query_var( 'paged' ) );
$query_args = array(
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'orderby' => $atts['orderby'],
'meta_key' => $atts['meta_key'],
'order' => $atts['order'],
'posts_per_page' => $atts['posts_per_page'],
'paged' => $page_number,
//'meta_query' => WC()->query->get_meta_query(),
//'tax_query' => WC()->query->get_tax_query(),
);
if ( ! empty( $atts['skus'] ) ) {
$query_args['meta_query'][] = array(
'key' => '_sku',
'value' => array_map( 'trim', explode( ',', $atts['skus'] ) ),
'compare' => 'IN',
);
}
if ( ! empty( $atts['ids'] ) ) {
$query_args['post__in'] = array_map( 'trim', explode( ',', $atts['ids'] ) );
}
$query_args['tax_query'][] = array(
'taxonomy' => WC_PRODUCT_VENDORS_TAXONOMY,
'operator' => 'EXISTS'
);
return poster_product_loop( $query_args, $atts, 'products' );
}
}
/**
* Adds Poster Product Grid to poster_products shortcode
*/
if ( ! function_exists('poster_product_loop') ){
function poster_product_loop( $query_args, $atts, $loop_name ) {
global $woocommerce_loop;
$columns = absint( $atts['columns'] );
$woocommerce_loop['columns'] = $columns;
$woocommerce_loop['name'] = $loop_name;
$query_args = apply_filters( 'woocommerce_shortcode_poster_product_query', $query_args, $atts, $loop_name );
$transient_name = 'wc_loop' . substr( md5( json_encode( $query_args ) . $loop_name ), 28 ) . WC_Cache_Helper::get_transient_version( 'product_query' );
$products = get_transient( $transient_name );
if ( false === $products || ! is_a( $products, 'WP_Query' ) ) {
$products = new WP_Query( $query_args );
set_transient( $transient_name, $products, DAY_IN_SECONDS * 30 );
}
ob_start();
if ( $products->have_posts() ) {
?>
<?php do_action( "woocommerce_shortcode_before_{$loop_name}_loop", $atts ); ?>
<?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(); ?>
<?php do_action( "woocommerce_shortcode_after_{$loop_name}_loop", $atts ); ?>
<?php
do_action('woocommerce_after_sms_user_poster_product_loop', $products);
} else {
do_action( "woocommerce_shortcode_{$loop_name}_loop_no_results", $atts );
}
woocommerce_reset_loop();
wp_reset_postdata();
//do_action( 'woocommerce_after_shop_loop' );
return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
}
}

Related

Custom shortcode displaying a loop of WooCommerce product variations

Im trying to make a custom shortcode in order to display some product variations that have no stock quantity with stock <= 0.
Here's what I did so far:
if( ! function_exists('preorable_products') ) {
// Add Shortcode
function preorable_products( $atts ) {
global $woocommerce_loop;
// Attributes
$atts = shortcode_atts(
array(
'columns' => '4',
'limit' => '20',
'preordable' => "yes",
'stock' => 0,
),
$atts, 'preorable_products'
);
$woocommerce_loop['columns'] = $atts['columns'];
// The WP_Query
$products_variation = new WP_Query( array (
'post_type' => 'product_variation',
'post_status' => 'publish',
'fields' => 'id=>parent',
'posts_per_page' => $atts['limit'],
'meta_query' => array(
'relation' => 'AND',
'preordable' => array(
'key' =>'_ab_preorder_checkbox',
'value' => "yes",
'compare' => '=='
),
'stock' => array(
'key' =>'_stock',
'value' => 0,
'compare' => '<='
),
)
));
$products = $products_variation;
ob_start();
if ( $products->have_posts() ) { ?>
<?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(); ?>
<?php
} else {
do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
echo "<p>Aucun article disponible à la précommande.</p>";
}
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';
}
add_shortcode( 'preorable_products', 'preorable_products' );
}
The WP Query part seems to work perfectly, but the code part to display the product seems wrong. I feel like $product variable doesn't have have_post method :
if ( $products->have_posts() ) { ?>
<?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(); ?>
<?php
} else {
do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
echo "<p>Aucun article disponible à la précommande.</p>";
}
woocommerce_reset_loop();
wp_reset_postdata();
return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';
Any help is welcome.
There are some errors and missing things in your code, use instead the following revisited code:
if( ! function_exists('get_preordable_products') ) {
function get_preordable_products( $atts ) {
// Shortcode Attributes
extract( shortcode_atts( array(
'columns' => '4',
'limit' => '20',
'preordable' => "yes",
'stock' => 0,
), $atts, 'preordable_products' ) );
// The WP_Query
$query = new WP_Query( array (
'post_type' => 'product_variation',
'post_status' => 'publish',
'posts_per_page' => $limit,
'meta_query' => array(
'relation' => 'AND',
'preordable' => array(
'key' =>'_ab_preorder_checkbox',
'value' => "yes",
'compare' => '=='
),
array(
'key' =>'_stock',
'value' => 0,
'compare' => '<='
),
)
) );
global $woocommerce_loop;
$woocommerce_loop['columns'] = $columns;
$woocommerce_loop['is_shortcode'] = 1;
$woocommerce_loop['name'] = 'preordable_products';
$woocommerce_loop['total'] = $query->post_count;
$woocommerce_loop['total_pages'] = $query->max_num_pages;
$woocommerce_loop['per_page'] = $limit;
ob_start();
if ( $query->have_posts() ) {
woocommerce_product_loop_start();
while ( $query->have_posts() ) {
$query->the_post();
wc_get_template_part( 'content', 'product' );
}
woocommerce_product_loop_end();
woocommerce_reset_loop();
wp_reset_postdata();
} else {
do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
echo '<p>'. __("Aucun article disponible à la précommande.") . '</p>';
}
$content = ob_get_clean();
return '<div class="woocommerce columns-' . $columns . '">' . $content . '</div>';
}
add_shortcode( 'preordable_products', 'get_preordable_products' );
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Usage: [preordable_products] or in Php code echo do_shortcode('[preordable_products]');

How can i hide a product category on woocommerce category list menu when all the products under this category are out of stock?

I have checked from Woocommerce--> Inventory the option to hide "out of stock" products from my eshop. Now, i am trying to find out how i can hide a category from category list menu widget that has only out of stock products. Any idea? Thanks in advance. i use iks menu plugin.
I tried
function exclude_categories( $category_list_args ) {
$args = array(
'hide_empty' => false,
'hierarchical' => true,
);
$product_categories = get_terms( 'product_cat', $args );
$exclude = array();
foreach ( $product_categories as $category ) {
$posts = get_posts( array( 'post_type' => 'product', 'posts_per_page' => -1, 'product_cat' => $category->slug, 'fields' => 'ids' ) );
$show_category = false;
foreach ( $posts as $post ) {
$product = new wC_Product( $post );
$visible_product = $product->is_visible();
if ( true === $visible_product ) {
$show_category = true;
break;
}
}
if ( false === $show_category ) {
$exclude[] = $category->term_id;
}
}
if ( ! empty( $exclude ) ) {
$category_list_args['exclude'] = implode( ',', $exclude );
unset( $category_list_args['include'] );
}
return $category_list_args;
}
add_filter( 'woocommerce_product_categories_widget_args', 'exclude_categories', 10, 1 );
Which hook should i use instead of woocommerce_product_categories_widget_args ? I use iks menus plugin to show on accordion the list of products categories. The code above works on Woocommerce Product Categories Widget but not on iks menu widget...
On iks menu plugin, the function that is responsible for showing the categories on widget sidebar is
private function get_WP_terms() {
$taxonomy = $this->get_taxonomy();
if ( $taxonomy ) {
$this->args = [
"taxonomy" => $taxonomy,
];
$this->save_args( [
"orderby",
"order",
"hide_empty",
"hierarchical",
"include",
"exclude",
"search",
"child_of",
"parent",
"childless",
] );
if ( version_compare( get_bloginfo( 'version' ), '4.5', '>=' ) ) {
$items = get_terms( $this->args );
} else {
$items = get_terms( $taxonomy, $this->args );
}
if ( is_array( $items ) ) {
if ( ! empty( $items ) ) {
$index = 0;
$show_posts = $this->settings_manager->get_value( "show_posts" );
/* Posts */
if ( $show_posts ) {
$post_type = Utils::get_post_type_by_taxonomy( $taxonomy );
$include = $this->settings_manager->get_value( "include" );
$has_include = ! empty( $include );
$posts = get_posts( [
'post_type' => $post_type,
'posts_per_page' => - 1,
'orderby' => 'date',
'order' => 'DESC',
'tax_query' => [
[
'taxonomy' => $taxonomy,
'operator' => $has_include ? 'IN' : 'EXISTS',
'terms' => $has_include ? Utils::get_terms_ids( $items ) : [],
]
],
'suppress_filters' => false // [Fix] WPML compatibility
] );
$posts_by_terms = [];
foreach ( $posts as $post ) {
$terms = get_the_terms( $post, $taxonomy );
if ( ! empty( $terms ) ) {
foreach ( $terms as $term ) {
if ( ! isset( $posts_by_terms[ $term->term_id ] ) ) {
$posts_by_terms[ $term->term_id ] = [];
}
$posts_by_terms[ $term->term_id ][] = $post;
}
}
}
}
foreach ( $items as $key => $item ) {
$id = (int) $item->term_id;
$link = get_term_link( $id );
$item_data = [
"id" => $id,
"title" => $item->name,
"link" => $link,
"parent" => (int) $item->parent,
"is_current" => $this->is_current_page_url( $link ) || $this->get_queried_object_term_id() === $id,
"is_term_includes_post" => $this->is_term_includes_post( $id, $this->get_taxonomy() ),
"is_page_includes_post" => false,
"index" => $index,
"is_expanded" => false,
"posts_count" => $item->count,
"is_post" => false,
"target" => null,
];
$index ++;
$this->data[] = $item_data;
if ( $show_posts ) {
if ( isset( $posts_by_terms[ $id ] ) ) {
$result_posts = $posts_by_terms[ $id ];
foreach ( $result_posts as $post ) {
$post_link = get_permalink( $post->ID );
$this->data[] = [
"id" => $post->ID,
"title" => $post->post_title,
"link" => $post_link,
"parent" => $id,
"is_current" => $this->is_current_page_url( $post_link ),
"is_term_includes_post" => false,
"is_page_includes_post" => false,
"index" => $index,
"is_expanded" => false,
"posts_count" => false,
"is_post" => true,
"target" => null,
];
$index ++;
}
}
}
}
}
i suppose that i need something like
'meta_query' => array(
array(
'key' => '_stock_status',
'value' => 'instock',
'compare' => '=',
)
)
but i am a little bit confused...
The only way we can find the post count per category was by getting all categories (terms) of product_cat. Then we looped through them - each time calling my function get_count and passing term_id. In the get_count we run a query to get all posts associated with it and we also pass post meta _stock_status = instock. This return all products where the stock status is in stock. Then we return found_posts attribute back - the IF statement then checks is the post count is bigger than 0.
The code (tested):
add_shortcode('test_test','test_test');
function test_test() {
$terms = get_terms('product_cat');
foreach($terms as $term) {
$post_count = get_count($term->term_id);
if($post_count > 0) {
echo $term->name . '<br>'; //This is where you put your category details
}
}
}
function get_count($cat_id) {
$args = array(
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'id',
'terms' => array($cat_id),
'include_children' => false
)
),
'posts_per_page' => -1,
'post_type' => 'product',
'post_status' => 'publish',
'meta_key' => '_stock_status',
'meta_value' => 'instock',
'meta_compare' => '='
);
$wp_query = new WP_Query($args);
wp_reset_postdata();
return $wp_query->found_posts;
}

Fetching custom post type/taxonomy with Wordpress shortcode

I have followed the Wordpress docs and have created this custom function/shortcode, for some reason I cannot get it to work.
/** Get Stories Shortcode **/
function register_shortcodes() {
add_shortcode( 'stories', 'stories_func' );
}
add_action( 'init', 'register_shortcodes' );
function stories_func( $atts ) {
global $wp_query, $post;
$atts = shortcode_atts( array(
'cat' => ''
), $atts );
$loop = new WP_Query( array(
'posts_per_page' => 4,
'post_type' => 'stories',
'orderby' => 'rand',
'tax_query' => array (
array (
'taxonomy' => 'story_category',
'field' => 'slug',
'terms' => array (sanitize_title($atts['cat']))
)
)
));
if( ! $loop->have_posts() ) {
return false;
}
while( $loop->have_posts() ) {
$loop->the_post();
echo the_title();
}
wp_reset_postdata();
}
The shortcode I am using is: [stories cat="Career Stories"]
Shortcode should always return value rather than echoing in the callback function. Please check following example. Shortcode output is collected using ob_get_contents() function and it is returned at the end.
function register_shortcodes() {
add_shortcode( 'stories', 'stories_func' );
}
add_action( 'init', 'register_shortcodes' );
function stories_func( $atts ) {
global $wp_query, $post;
$atts = shortcode_atts( array(
'cat' => ''
), $atts );
$loop = new WP_Query( array(
'posts_per_page' => 4,
'post_type' => 'stories',
'orderby' => 'rand',
'tax_query' => array (
array (
'taxonomy' => 'story_category',
'field' => 'slug',
'terms' => array (sanitize_title($atts['cat']))
)
)
));
if( ! $loop->have_posts() ) {
return false;
}
ob_start();
while( $loop->have_posts() ) {
$loop->the_post();
the_title();
}
wp_reset_postdata();
$output = ob_get_contents();
ob_end_clean();
return $output;
}
Here is updated code.
function register_shortcodes() {
add_shortcode( 'stories', 'stories_func' );
}
add_action( 'init', 'register_shortcodes' );
/**
* Produtos Shortcode Callback
*
* #param Array $atts
*
* #return string
*/
function stories_func( $atts ) {
global $wp_query,
$post;
$terms = get_terms( array(
'taxonomy' => 'story_category',
'hide_empty' => false,
) );
foreach($terms as $term)
{
$term_slugs[] = $term->slug;
}
$atts = $term_slugs;
$loop = new WP_Query( array(
'posts_per_page' => 4,
'post_type' => 'stories',
'orderby' => 'rand',
'tax_query' => array( array(
'taxonomy' => 'story_category',
'field' => 'slug',
'terms' => $atts
) )
) );
if( ! $loop->have_posts() ) {
return false;
}
while( $loop->have_posts() ) {
$loop->the_post();
echo the_title();
}
wp_reset_postdata();
}
Tested and works well

Woocommerce Related Product exclude current product in Sub categories

I Having trouble to exclude the current product in related product Woocommerce,
now i have change the related product from category to subcategory (without child). SO the related product will only display the subcategory product (same subcategory) but now it will also display the current product. anyone one have solution> Thank You
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product, $woocommerce_loop;
if ( empty( $product ) || ! $product->exists() ) {
return;
}
if ( ! $related = $product->get_related( $posts_per_page ) ) {
return;
}
$cats_array = array(0);
// 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;
}
$args = apply_filters( 'woocommerce_related_products_args', array(
'exclude' => array( $cur_product_id ),
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'post__not_in' => array( $cur_product_id ),
'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 );
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 wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
</div>
<?php endif;
wp_reset_postdata();
Your problem is $cur_product_id variable!
Change with this:
$product->get_the_id()
Thank You so much. I found the solution
By adding this
$terms = wp_get_post_terms( $product->id, 'product_cat' );
and this 'post__not_in' => array( $cur_product_id ),
Here is the code
if ( ! defined( 'ABSPATH' ) ) {
exit;
}
global $product, $woocommerce_loop;
if ( empty( $product ) || ! $product->exists() ) {
return;
}
if ( ! $related = $product->get_related( $posts_per_page ) ) {
return;
}
$cats_array = array(0);
// The current product id (Woocommerce version retro compatible)
$cur_product_id = method_exists( $product, 'get_id' ) ? $product->get_id() : $product->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;
}
$args = apply_filters( 'woocommerce_related_products_args', array(
'exclude' => array( $cur_product_id ),
'post_type' => 'product',
'ignore_sticky_posts' => 1,
'post__not_in' => array( $cur_product_id ),
'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 );
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 wc_get_template_part( 'content', 'product' ); ?>
<?php endwhile; // end of the loop. ?>
<?php woocommerce_product_loop_end(); ?>
</div>
<?php endif;
wp_reset_postdata();

How do I get woocommerce product listing to show all products in one page?

I have the following category within a site:
http://rivetnuttool.com/site/product-category/blue-pneumatic-rivet-nut-tools/
And I want it to show all of the 7 products within the first page, and even if I have 100 products to show them in one single page.
I have tried with different solutions like adding this to my functions.php file:
add_filter( 'loop_shop_per_page', create_function( '$cols', 'return -1;' ) );
Rewriting the shortcode like the solution proposed here http://ideas.woothemes.com/forums/133476-woocommerce/suggestions/4146798-add-pagination-support-for-list-of-products-render
And several other online options, and none of them seems to work, I allways get the pagination and the limit.
The theme used in the site is Divi.
Just add the conditional check to your functions.php file:
if( isset( $_GET['showall'] ) )
{
add_filter( 'loop_shop_per_page', create_function( '$cols', 'return -1;' ) );
}
else
{
add_filter( 'loop_shop_per_page', create_function( '$cols', 'return 12;' ) );
}
loop_shop_per_page is the correct filter. If you aren't seeing any effect, then add a later priority. In my test case my parent theme was filtering loop_shop_per_page so my child theme's filter wasn't doing anything.
add_filter( 'loop_shop_per_page', 'so_31843880_show_all_products', 20 );
function so_31843880_show_all_products(){
return -1;
}
To apply the filter to only product categories you would add some conditional logic:
add_filter( 'loop_shop_per_page', 'so_show_all_products' );
function so_31843880_show_all_products($per_page){
if( is_taxonomy('product_cat') ){
$per_page = -1;
}
return $per_page;
}
I corrected and changed the custom code from the above blog post to:
function shortcode_settori( $atts ) {
global $woocommerce_loop;
extract( shortcode_atts( array(
'per_page' => '24',
'columns' => '4',
'orderby' => 'title',
'order' => 'desc',
'settore' => '', // Slugs
'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'.
), $atts ) );
if ( ! $settore ) {
return '';
}
$paged = (get_query_var('paged')) ? get_query_var('paged') : 1;
// Default ordering args
$ordering_args = WC()->query->get_catalog_ordering_args( $orderby, $order );
$args = array(
'post_type' => 'product',
'post_status' => 'publish',
'ignore_sticky_posts' => 1,
'posts_per_page' => '999',
'meta_query' => array(
array(
'key' => '_visibility',
'value' => array('catalog', 'visible'),
'compare' => 'IN'
)
),
'tax_query' => array(
array(
'taxonomy' => 'product_cat',
'field' => 'term_id', //This is optional, as it defaults to 'term_id'
'terms' => $settore,
'operator' => 'IN' // Possible values are 'IN', 'NOT IN', 'AND'.
)
)
);
$products = new WP_Query($args);
$woocommerce_loop['columns'] = $columns;
if ( $products->have_posts() ) : ?>
<?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(); ?>
<?php endif;
if($products->max_num_pages>1){
?>
<nav class="woocommerce-pagination">
<?php
echo paginate_links( apply_filters( 'woocommerce_pagination_args', array(
'base' => esc_url( str_replace( 999999999, '%#%', remove_query_arg( 'add-to-cart', get_pagenum_link( 999999999, false ) ) ) ),
'format' => '',
'current' => max( 1, get_query_var( 'paged' ) ),
'total' => $products->max_num_pages,
'prev_text' => '←',
'next_text' => '→',
'type' => 'list',
'end_size' => 3,
'mid_size' => 3
) ) );
?>
</nav>
<?php }
woocommerce_reset_loop();
wp_reset_postdata();
echo $return;
$return = '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
// Remove ordering query arguments
WC()->query->remove_ordering_args();
return $return;
}
add_shortcode( 'prodotti_per_settore', 'shortcode_settori' );
And everything works now.
Now, in 2019, I just adjust a parameter in a Customize panel by:
Apperance>Customize>WooCommerce Options>Shop Archive sidebar layout>total products per page
Then, fill the number I want into that.

Categories