Skip to content

Instantly share code, notes, and snippets.

@filipecsweb
Last active April 14, 2024 18:09
Show Gist options
  • Save filipecsweb/32467a20f2eeb39b0cbf to your computer and use it in GitHub Desktop.
Save filipecsweb/32467a20f2eeb39b0cbf to your computer and use it in GitHub Desktop.
WooCommerce shortcode to output product categories randomly
<?php
/**
* Create the new WooCommerce shortcode [random_product_categories] to output product categories randomly.
* Based on [product_categories] (/plugins/woocommerce/includes/class-wc-shortcodes.php).
*
* This new shortcode accepts all attributes used by [product_categories], except 'orderby' and 'order', of course.
* See more at @link https://woocommerce.com/document/woocommerce-shortcodes/.
*
* @param array $atts User defined attributes in shortcode tag.
*/
function random_product_categories_shortcode( $atts ) {
global $woocommerce_loop;
$atts = shortcode_atts( [
'number' => null,
'columns' => '4',
'hide_empty' => 1,
'parent' => '',
'ids' => '',
'hide_title' => 0,
], $atts );
if ( isset( $atts['ids'] ) ) {
$ids = explode( ',', $atts['ids'] );
$ids = array_map( 'trim', $ids );
} else {
$ids = [];
}
$hide_empty = (bool) $atts['hide_empty'];
// Get terms and workaround WP bug with parents/pad counts.
$args = [
'hide_empty' => $hide_empty,
'include' => $ids,
'pad_counts' => true,
'child_of' => $atts['parent']
];
$product_categories = get_terms( 'product_cat', $args );
// Shuffle the array of objects `$product_categories`.
shuffle( $product_categories );
if ( '' !== $atts['parent'] ) {
$product_categories = wp_list_filter( $product_categories, [ 'parent' => $atts['parent'] ] );
}
if ( $hide_empty ) {
foreach ( $product_categories as $key => $category ) {
if ( $category->count == 0 ) {
unset( $product_categories[ $key ] );
}
}
}
if ( $atts['number'] ) {
$product_categories = array_slice( $product_categories, 0, $atts['number'] );
}
$columns = absint( $atts['columns'] );
$woocommerce_loop['columns'] = $columns;
ob_start();
// Reset loop/columns globals when starting a new loop.
$woocommerce_loop['loop'] = $woocommerce_loop['column'] = '';
if ( $product_categories ) {
woocommerce_product_loop_start();
if ( ! empty( $atts['hide_title'] ) ) {
remove_action( 'woocommerce_shop_loop_subcategory_title', 'woocommerce_template_loop_category_title' );
}
foreach ( $product_categories as $category ) {
wc_get_template( 'content-product-cat.php', [
'category' => $category
] );
}
if ( ! empty( $atts['hide_title'] ) ) {
add_action( 'woocommerce_shop_loop_subcategory_title', 'woocommerce_template_loop_category_title' );
}
woocommerce_product_loop_end();
}
wc_reset_loop();
return '<div class="woocommerce columns-' . $columns . '">' . ob_get_clean() . '</div>';
}
add_shortcode( 'random_product_categories', 'random_product_categories_shortcode' );
@filipecsweb
Copy link
Author

filipecsweb commented Nov 1, 2022

@Hebhansen this code shows all categories because this is the default.

See, number is set to null which means all categories are output. If you want to show less then write something like [random_product_categories number=8].

Regarding your question about the columns, it does respect the variable columns on e.g. [random_product_categories columns=2].

About removing title, for sure you can. You could for example copy the template content-product-cat.php to your theme and then edit the way you want.

@Hebhansen
Copy link

@filipecsweb Thx for your reply. This code is just awesome. For real! I don't get why it is not included in Woo core!

I was using limit attribute for showing only 3. The one used for products. number attribute does the job thx. As you can probably tell, I am not a coder myself. I do css and xml, but php is too wild for me.

content-product_cat is that available here at Github?

Again thx really

@filipecsweb
Copy link
Author

filipecsweb commented Nov 5, 2022

@Hebhansen I updated the code so you can hide the title.
You'd have to use the following shortcode: [random_product_categories hide_title=1].

Regarding the file "content-product-cat.php", in other words if you want more control over the output you'd have to copy the file "/wp-content/plugins/woocommerce/templates/content-product-cat.php" to "yourtheme/woocommerce/content-product-cat.php". More details at https://woocommerce.com/document/template-structure-overriding-templates-via-a-theme/#how-to-edit-files.

This is called "template override". It might seem a bit confusing in the beginning if you never did it, but it's something very easy to do.

@Hebhansen
Copy link

@filipecsweb Thx man. That is just incredibly awesome. It works perfectly. Just a question, you may know the answer to. When I am log'ed into my site everything Random works perfect. When I am not, nothing Random works. Du you have any idea what plugin or function causes this?

@filipecsweb
Copy link
Author

filipecsweb commented Nov 5, 2022

@Hebhansen the first thing that came to me is cache. Do you have any cache plugins active? Wp fastest cache, wp rocket, etc...
Those cache plugins normally don't cache your page if you're logged in, but the page is cached if you're not, which means the random magic wouldn't work on every page request.

@Hebhansen
Copy link

@Hebhansen the first thing that came to me is cache. Do you have any cache plugins active? Wp fastest cache, wp rocket, etc... Those cache plugins normally don't cache your page if you're logged in, but the page is cached if you're not, which means the random magic wouldn't work on every page request.

Hey Filip

So two years later I am still a fan. 2 years ago I remember changing a setting in my cache that sorted random. I do not remember what setting!

I have now made a new site, and I am back at square one. Something blocks random from working for all users, also admin. I have Litespeed cache now. Do you happen to know this fix? You may see this on my frontpage at svalinnart.com where only categories under themes and genres are supposed to be random (where 4 cats shows)

Finally, do you know how to hide overflow on mouse over? I have a zoom effect on the cat image, but I cannot get it to clip the overflow.

All the best

@filipecsweb
Copy link
Author

@Hebhansen It seems the cache comes from Cloudflare. You'd have to correctly setup your cache settings under the Cloudflare platform and/or under any WP plugin that integrates your website with Cloudflare.

About the overflow I couldn't reproduce what you described.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment