0
votes

I am creating a custom sort name "price-asc" which sort products based on highest price.

My solution is:

1- create key_meta called "_highest_price" to store the highest price for each product

2- create a custom "price-asc" in filter woocommerce_catalog_orderby

3- custom "orderby", "order", "meta_key" in filter woocommerce_get_catalog_ordering_args

functions.php

// step 1
function my_save_post_product( $post_id, $post, $update ) {
  if( ! $update )   // no further actions if no changes
    return;

  if( $post->post_status !== 'publish' )    // no further actions if product is not public
    return;

  $product = wc_get_product( $post_id );

  if( $product->product_type == 'variable' ) :
    update_post_meta( $post_id, '_highest_price', $product->get_variation_price( 'max', true ) );
  elseif( $product->product_type == 'simple' ) :
    update_post_meta( $post_id, '_highest_price', $product->get_price() );
  endif;
}
add_action( 'save_post_product', 'my_save_post_product', 10, 3 );

// step 2
function my_woocommerce_catalog_orderby( $options ) {
  //...
  $options['price-asc'] = __( 'A different low to high', 'mytheme' );
  return $options;
}
add_filter( 'woocommerce_catalog_orderby', 'my_woocommerce_catalog_orderby' );

// step 3
function my_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 ( $orderby_value == 'price-asc' ) :
    $args['orderby'] = 'meta_value_num';
    $args['order'] = 'ASC';
    $args['meta_key'] = '_highest_price';
  endif;

  return $args;
}
add_filter( 'woocommerce_get_catalog_ordering_args', 'my_woocommerce_get_catalog_ordering_args' );

Then I go to https://example.com/products/?orderby=price-asc

However, the order doesn't display as expected. Product with _highest_price "22092" should displays before product with _highest_price "1177000" as 22092 < 1177000.

Here are my database and display. Please help database display

1
WooCommerce allow you change change default sort: endocreative.com/customize-product-sorting-woocommercemarcelo2605

1 Answers

0
votes

After a while, I finally got my answer. I just simply changed "price-asc" to "price_asc". Why?

In woocommerce\includes\class-wc-query.php

before line 461: $orderby_value = "price-asc"

line 461:

$orderby_value = is_array( $orderby_value ) ? $orderby_value : explode( '-', $orderby_value );

after this line $orderby_value is an array with [0] => "price", [1] => "asc"

line 462:

$orderby       = esc_attr( $orderby_value[0] );

this time, $orderby = "price" which tells the system continuously runs at lines 498-501

case 'price':
  $callback = 'DESC' === $order ? 'order_by_price_desc_post_clauses' : 'order_by_price_asc_post_clauses';
  add_filter( 'posts_clauses', array( $this, $callback ) );
  break;

=> it's wrong. $orderby should not be "price" at the end.

My suggestion: it might only apply for keyword "price" but for the future, we should name our sorting id with "_" instead of "-". E.g custom_sort_id instead of custom-sort-id.