Support » Plugin: WooCommerce » Category order by SKU shortcode?

  • Resolved JapeNZ

    (@japenz)


    Hello!
    I’m trying to display category/product listings on various pages by their SKU’s using shortcodes but can’t get it to work, here’s my latest attempt:

    [product_category category=”uncanny-x-men-vol-3″ per_page=”99″ columns=”5″ orderby=”meta_value” order=”desc” meta_key=”_sku”]

    I was able to get the order for every category to change using this:

    add_filter('woocommerce_get_catalog_ordering_args', 'am_woocommerce_catalog_orderby');
    function am_woocommerce_catalog_orderby( $args ) {
        $args['meta_key'] = '_sku';
        $args['orderby'] = 'meta_value';
        return $args;
    }

    but I don’t want it applied to everything and it overrides the other category views I have set up (‘date’, ‘rand’, ‘title’)

    Any help would be very much appreciated:)

    https://wordpress.org/plugins/woocommerce/

Viewing 9 replies - 1 through 9 (of 9 total)
  • So I can set Default Product Sorting to ‘SKU: Descending’ using this code:

    add_filter( 'woocommerce_get_catalog_ordering_args', 'custom_woocommerce_get_catalog_ordering_args' );
    
    function custom_woocommerce_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 ( 'sku_desc' == $orderby_value ) {
    		$args['orderby'] = 'meta_value';
    		$args['order'] = 'desc';
    		$args['meta_key'] = '_sku';
    	}
    
    	return $args;
    }
    
    add_filter( 'woocommerce_default_catalog_orderby_options', 'custom_woocommerce_catalog_orderby' );
    add_filter( 'woocommerce_catalog_orderby', 'custom_woocommerce_catalog_orderby' );
    
    function custom_woocommerce_catalog_orderby( $sortby ) {
    	$sortby['sku_desc'] = 'SKU: Descending';
    	return $sortby;
    }

    But this stops the shortcodes I have on some pages using ‘title’, ‘date’ and ‘rand’ from working?!

    [product_category category="xmenv2" per_page="99" columns="5" orderby="date" order="desc" meta_key=""]

    Is there some code I can add to ‘SKU: Descending’ that will allow custom ordering so I can have ‘custom ordering + SKU: Descending’ as an alternative to ‘default sorting (custom ordering + name)’?

    Any help would be very much appreciated:)

    Okay so I think I’ve managed to come up with a solution.

    Rather than set SKU: Descending as default I’ve used the following code to add sku as a shortcode option:

    <?php
    /**
    	 * Returns an array of arguments for ordering products based on the selected values
    	 *
    	 * @access public
    	 * @return array
    	 */
    	public function get_catalog_ordering_args( $orderby = '', $order = '' ) {
    		// Get ordering from query string unless defined
    		if ( ! $orderby ) {
    			$orderby_value = isset( $_GET['orderby'] ) ? wc_clean( $_GET['orderby'] ) : apply_filters( 'woocommerce_default_catalog_orderby', get_option( 'woocommerce_default_catalog_orderby' ) );
    
    			// Get order + orderby args from string
    			$orderby_value = explode( '-', $orderby_value );
    			$orderby       = esc_attr( $orderby_value[0] );
    			$order         = ! empty( $orderby_value[1] ) ? $orderby_value[1] : $order;
    		}
    
    		$orderby = strtolower( $orderby );
    		$order   = strtoupper( $order );
    
    		$args = array();
    
    		// default - menu_order
    		$args['orderby']  = 'menu_order title';
    		$args['order']    = $order == 'DESC' ? 'DESC' : 'ASC';
    		$args['meta_key'] = '';
    
    		switch ( $orderby ) {
    			case 'rand' :
    				$args['orderby']  = 'rand';
    			break;
    			case 'date' :
    				$args['orderby']  = 'date';
    				$args['order']    = $order == 'ASC' ? 'ASC' : 'DESC';
    			break;
    			case 'price' :
    				$args['orderby']  = 'meta_value_num';
    				$args['order']    = $order == 'DESC' ? 'DESC' : 'ASC';
    				$args['meta_key'] = '_price';
    			break;
    			case 'popularity' :
    				$args['meta_key'] = 'total_sales';
    
    				// Sorting handled later though a hook
    				add_filter( 'posts_clauses', array( $this, 'order_by_popularity_post_clauses' ) );
    			break;
    			case 'rating' :
    				// Sorting handled later though a hook
    				add_filter( 'posts_clauses', array( $this, 'order_by_rating_post_clauses' ) );
    			break;
    			case 'title' :
    				$args['orderby']  = 'title';
    				$args['order']    = $order == 'DESC' ? 'DESC' : 'ASC';
    			break;
    			case 'sku' :
    				$args['orderby']  = 'meta_value';
    				$args['order']    = $order == 'DESC' ? 'DESC' : 'ASC';
    				$args['meta_key'] = '_sku';
    			break;
    		}
    
    		return apply_filters( 'woocommerce_get_catalog_ordering_args', $args );
    	}

    I copied the majority of this from woocommerce / includes / class-wc-shortcodes.php and added:

    case 'sku' :
    				$args['orderby']  = 'meta_value';
    				$args['order']    = $order == 'DESC' ? 'DESC' : 'ASC';
    				$args['meta_key'] = '_sku';
    			break;

    to the list.

    The result being I can now add use “sku” as orderby= in product category shortcodes… sweet! Haha!

    [product_category category="x-men-vol-4" per_page="99" columns="5" orderby="sku" order="desc" meta_key=""]

    You need to create a new file called class-wc-query.php in your child theme:

    public_html/wp-content/themes/’your child theme’/woocommerce/includes

    and then paste the code in there.

    JapeNZ,
    I’d like to do the same but this didn’t work for me. Is the idea here to override the core file? Did you include all the other functions in class-wc-query.php along with your custom function?

    Anyone who knows,
    Is there a way to do what JapeNZ did using a filter instead?

    Hi ericbakuladavis,

    Unfortunately since I posted this an update to Woocommerce seems to mean you can’t apply changes to the class-wc-query.php file via your child theme.
    At present I’m applying the same fix directly into the Woocommerce class-wc-query.php file.
    It works fine but each time there’s an update I have to reapply the fix.
    If you can find an alternative way of doing this I would be very keen to hear it:)

    Cheers,
    JP

    Hi JapeNZ,

    I found a solution! I put this in my functions.php

    add_filter('woocommerce_shortcode_products_query', 'add_sku_to_shortocde_orderby_options', 10, 2);
    
    function add_sku_to_shortocde_orderby_options ($args, $atts) {
    
    	if ($atts['orderby'] == "sku") {
    
    		$args['orderby']  = 'meta_value';
    		$args['order']    = $order == 'DESC' ? 'DESC' : 'ASC';
    		$args['meta_key'] = '_sku';
    	}
    
    	return $args;
    	return $atts;
    }

    I tested it with a shortcode like this:

    [product_category category="my-category" orderby="sku"]

    …and it worked.

    Thanks to you for providing everything inside the if statement. I’m not sure, but it looks like it could be adaptable to any meta_key.

    I confirmed it can be adapted to allow products output by shortcode to be sorted according to Custom Field values defined in the Admin Panel. I suspect it can be adapted to work with existing product meta keys as well (there are many).

    It also works with other types of shortcodes such as:
    [products ids="1, 2, 3, 4, 5, 6, 7, 8" orderby="whatever"]

    You are a legend! 😀
    This is perfect, thank you so much.

    I couldn’t get the:

    $args['order'] = $order == 'DESC' ? 'DESC' : 'ASC';

    to allow for asc or desc, it just defaults to ‘asc’.
    As I need it to be ‘desc’ I switched the line to:

    $args['order'] = 'desc';

    so it now defaults to ‘desc’… perfect!

    I only mention this in case someone else needs the info:)

    Thanks again buddy!

    I’m glad it worked for you!

    Thanks for pointing out the issue with: $args['order'] = $order == 'DESC' ? 'DESC' : 'ASC';

    I removed that line and now it works normally: defaults to desc but still allows asc to be defined in the shortcode.

    I found a spelling error in my function name… Here’s the updated code:

    add_filter('woocommerce_shortcode_products_query', 'add_shortcode_orderby_options', 10, 2);
    
    function add_shortcode_orderby_options ($args, $atts) {
    
    	if ($atts['orderby'] == "sku") {
    
    		$args['orderby']  = 'meta_value';
    		$args['meta_key'] = '_sku';
    	}
    
    	return $args;
    	return $atts;
    }

    Remove the line… REMOVE THE LINE!!!
    Perfect!

    I’ve done the same and it works exactly as described, thanks again for looking into this you have made my day 🙂

    Kind regards,
    JP

Viewing 9 replies - 1 through 9 (of 9 total)
  • The topic ‘Category order by SKU shortcode?’ is closed to new replies.