phpwordpresssortingwoocommercemetadata

WooCommerce products custom numerical sorting option by specific metadata


Im having an issue with ordering my products, I have a meta value in each of the products called "cheapest_worktop" with a NUMERIC value,

Im using the fiter "woocommerce_get_catalog_ordering_args" to alter the query so that it sorts by the meta value:

 $args["meta_key"] = "cheapest_worktop";
 $args["orderby"] = "meta_value_num";
 $args["meta_type"] = 'DECIMAL';
 $args["order"] = "ASC";
 $args["meta_query"] = array(
     'relation' => 'AND',
     array(
         'key' => "cheapest_worktop",
         'compare' => 'EXISTS', // Only retrieve products where the meta key exists
     )
 );

but it ends up showing products with and without the meta key,

It only works when I remove the

 $args["meta_key"] = "cheapest_worktop";

That then hides the products that don't have the meta_key but it then doesn't sort it, It was initially just

$args["meta_key"] = "cheapest_worktop";
$args["orderby"] = "meta_value_num";
$args["meta_type"] = 'DECIMAL';
$args["order"] = "ASC";

That did work then for some reason it just stopped working not 100% as to why as no other changes happened on the website, no updates, no new plugins or code nothing.

I used

global $wp_query;
echo print_r($wp_query, true);
echo print_r($args, true);

To double check the $args being executed and they came back correct.

Any advice would be appreciated.


Solution

  • I suppose that you added a custom "cheapest worktop" sorting option, something like:

    add_filter( 'woocommerce_catalog_orderby', 'add_catalog_orderby_cheapest_worktop' );
    function add_catalog_orderby_cheapest_worktop( $orderby ) {
        $orderby['cheapest_worktop'] = __('Sort by cheapest worktop', 'woocommerce');
        return $orderby;
    }
    

    Now, as $args argument only handles 'orderby' and 'order', but not 'meta_query', you will try the following instead:

    add_filter( 'woocommerce_get_catalog_ordering_args', 'get_catalog_ordering_by_cheapest_worktop', 10, 3 );
    function get_catalog_ordering_by_cheapest_worktop( $args, $orderby, $order ) {
        if ( isset( $_GET['orderby'] ) && $_GET['orderby'] === 'cheapest_worktop' ) {
            // Custom sorting order
            $args['orderby'] = array(
                'meta_value_num' => 'ASC', // Sort numerically ascending
            );
        }
        return $args;
    }
    
    // Here we set the query (meta query)
    add_filter( 'woocommerce_product_query', 'product_query_by_cheapest_worktop', 10, 1 );
    function product_query_by_cheapest_worktop( $q ) {
        if ( isset($_GET['orderby']) && $_GET['orderby'] === 'cheapest_worktop' ) {
            $meta_query = $q->get('meta_query');
    
            $meta_query['relation'] = 'AND';
    
            $meta_query[] = array(
                'key'     => 'cheapest_worktop',
                'value'   => 0,
                'compare' => '>=',
                'type'    => 'NUMERIC',
            );
    
            $q->set('meta_query', $meta_query);
            $q->set('orderby', array(
                'meta_value_num' => 'ASC', // Sort numerically ascending
            ) );
        }
    }
    

    It should work.