By default, WooCommerce comes with 6 sorting options:
- Sort by popularity
- Sort by average rating
- Sort by newness
- Sort by price: low to high
- Sort by price: high to low
In this example, I’ll add an extra option to sort by sale status.
Adding a new sorting option
woocommerce_catalog_orderby hook gives you control over the default sorting options to display. In order to add a new option, you need to add it to the current options array.
Code:
1 2 3 4 5 6 7 |
function theme_catalog_orderby( $catalog_orderby_options ) { $catalog_orderby_options['sale'] = __( 'Sort by sale status', 'textdomain' ); return $catalog_orderby_options; } add_filter( 'woocommerce_catalog_orderby', 'theme_catalog_orderby' ); |
Now add the following code to order by the _sale_price custom field.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
/** * Returns an array of arguments for ordering products based on the selected values. * * @uses woocommerce_get_catalog_ordering_args hook * @return array */ function theme_get_catalog_ordering_args( $args ) { $orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) ); if ( 'sale' == $orderby_value ) { $args['meta_key'] = '_sale_price'; $args['orderby'] = 'meta_value_num'; $args['order'] = 'DESC'; } return $args; } add_filter( 'woocommerce_get_catalog_ordering_args', 'theme_get_catalog_ordering_args' ); |
Advanced sorting
However, if your sorting needs are more advanced, then you can hook into pre_get_posts instead of woocommerce_get_catalog_ordering_args.
The pre_get_posts hook gives developers access to the $query object and possibility to modify the query. It’s really powerful and useful for altering the main loop and creating custom queries. See the docs here.
In this example, we’ll show products from a given category ‘Cars’ and sort them by sale status.
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
/** * Get products from Cars category and sort by sale status. * * Alter the main loop * * @uses pre_get_posts hook */ function theme_modify_the_main_query( $query ) { // Order by: sale if ( isset( $_GET['orderby'] ) && $_GET['orderby'] == 'sale' ) { // Modify the main query if( ! is_admin() && $query->is_main_query() ) { // Get from Cars category $tax_query = array( array( 'taxonomy' => 'product_cat', 'field' => 'slug', 'terms' => 'cars' // Cars category (term) slug ) ); $query->set( 'tax_query', $tax_query ); $query->set( 'meta_key', '_sale_price' ); $query->set( 'orderby', 'meta_value_num' ); $query->set( 'order', 'DESC' ); } } } add_action( 'pre_get_posts', 'theme_modify_the_main_query' ); |
Great post. Currently, I am having a similar problem in which I guess you can help me!
I have a meta key value pair like this: key: ‘woodate’, value: ’01 Sep, 2017′) for products which belong to event category.
So I want to sort these event category products(on category archive page) in ASC order by the ‘woodate’ key.
Can you please suggest how to do that? I have many ways but it’s not working.
Hi Ranjan,
Try this code: https://pastebin.com/heHyWjA7 Change Line #19 ‘terms’ to your product event category slug. Also, change #line 27 $query->set( ‘order’, ‘DESC’ ) to ASC. ‘meta_value_num’ – Allows you to order by numeric meta value, but ‘woodate’ is string so you need to convert it to integer (timestamp) first or create a new meta key e.g. woodate_timestamp with timestamp value. You can use strtotime() function.
Hi. I’ve tried several different code snippets from various places on the web but none have worked for me. I’m using Toolset to create a set of custom fields and have a Size field with the slug pm-machine-size-a. I’d like to sort by Size; the sort option appears in the dropdown but selecting it has no product found. Every item in the inventory has that custom field populated. Can you coach me on where I’m making a mistake, please?
//add Size to catalog sort
function theme_catalog_orderby( $catalog_orderby_options ) {
$catalog_orderby_options['size'] = __( 'Sort by Size', 'woocommerce' );
return $catalog_orderby_options;
}
add_filter( 'woocommerce_catalog_orderby', 'theme_catalog_orderby' );
/**
* Returns an array of arguments for ordering products based on the selected values.
*
* @uses woocommerce_get_catalog_ordering_args hook
* @return array
*/
function theme_get_catalog_ordering_args( $args ) {
$orderby_value = isset( $_GET['orderby'] ) ? woocommerce_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
if ( 'size' == $orderby_value ) {
$args['meta_key'] = 'pm-machine-size-a';
$args['orderby'] = 'meta_value_num';
$args['order'] = 'DESC';
}
return $args;
}
add_filter( 'woocommerce_get_catalog_ordering_args', 'theme_get_catalog_ordering_args' );
Hi Michael,
Sorry I’m on a short vacation. I’ll be able to help you on Monday. But, this $args[‘orderby’] = ‘meta_value_num’; means that your meta key should be a numerical value so if you have a string value, then it won’t work. This $args[‘orderby’] might be a problem.
How can I display sorting system with my custom query?
I’ve a custom query for showing woocommerce product. Now I want to show sorting system above my query. Like shop page.
http://prntscr.com/ijjowy
I’ve tried lots of ways. But no success. Also I’ve followed this Article but result same,
Here is my query codes
https://pastebin.com/vGpDT7cd
Which code do I need for show sorting system. Please add that code in my query
I want to Woocommerce default all sorting list like Default sorting, Sort by popularity, Sort by average rating, Sort by newness, Sort by price: low to high, Sort by price: high to low,
Advance Thanks for help.
I’ve posted on stackoverflow, but still didn’t get help yet. please help me.
https://stackoverflow.com/questions/48920978/how-can-i-display-sorting-system-with-my-custom-query
very good tanks.