WordPress.org

Forums

WooCommerce - excelling eCommerce
[resolved] Category order by SKU shortcode? (10 posts)

  1. JapeNZ
    Member
    Posted 9 months ago #

    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/

  2. JapeNZ
    Member
    Posted 9 months ago #

    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:)

  3. JapeNZ
    Member
    Posted 9 months ago #

    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.

  4. ericbakuladavis
    Member
    Posted 1 month ago #

    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?

  5. JapeNZ
    Member
    Posted 1 month ago #

    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

  6. ericbakuladavis
    Member
    Posted 1 month ago #

    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.

  7. ericbakuladavis
    Member
    Posted 1 month ago #

    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"]

  8. JapeNZ
    Member
    Posted 1 month ago #

    You are a legend! :D
    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!

  9. ericbakuladavis
    Member
    Posted 1 month ago #

    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;
    }
  10. JapeNZ
    Member
    Posted 1 month ago #

    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

Reply

You must log in to post.

About this Plugin

  • WooCommerce - excelling eCommerce
  • Frequently Asked Questions
  • Support Threads
  • Reviews

About this Topic